How to check if any property of a ViewModel has been filled - c#

I have a ViewModel which contains properties that can optionally be filled from the user of my web application (e.g. first name, last name, e-mail, date of birth etc). These properties include several types like string, bool int, decimal, double, DateTime. All these types can be both nullable and non-nullable in the ViewModel.
If at least 1 of these properties has been filled in, then I have to create a database record. Do you have any idea for a way to check if any of these optional values has been filled?

You can implement this code, pass your viewmodel, then count how much fields are not null, if the return value>0, then you can implement your Db work.
public int MethodToCheckNotNull(ViewModel obj)
{
int i = 0;
PropertyInfo[] properties = typeof(obj).GetProperties();
foreach (PropertyInfo property in properties)
{
if (property.GetValue(obj) != null)
{
i++;
}
}
return i;
}

By convention, primitive data types are required. You can make the properties nullable which are primitive like int, double, DateTime vs. Then:
PropertyInfo[] infos = yourObjectInstance.GetType().GetProperties();
int count = 0;
for(int i = 0; i < infos.Length; i++)
{
if(infos[i].PropertyType == typeof(string))
{
string stringValue = infos[i].GetValue(yourObjectInstance).ToString().Trim();
if(!string.IsNullOrEmpty(body))
{
count++;
}
continue;
}
if(infos[i].GetValue(yourObjectInstance) != null)
{
count++;
}
}
if(count == 0)
{
// Handle error
}
// Create record

Related

Nhibernate Interceptor - Get Property length OnSave

I have simple NHibernate interceptor and override method OnSave().
Now what I am trying to do here is to get SQL length for string properties.
Is that possible.
I can see that property IType[] types contains SqlType where Length is available, but just cannot find how to read it. Example from debug:
This is example of the code which I have, and where I am trying to get Sql length of property.
public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types)
{
for (int i = 0; i < propertyNames.Length; i++)
{
//If type is string
if (types[i].GetType() == typeof(NHibernate.Type.StringType))
{
//Get SQL length of string property
}
}
return false;
}
Any help how I can get this?
Let's just try to cast the IType into intended one:
//If type is string
var stringType = types[i] as NHibernate.Type.StringType;
//if (types[i].GetType() == typeof(NHibernate.Type.StringType))
if(stringType != null)
{
//Get SQL length of string property
var length = stringType.SqlType.Length;
}

EF Code First Pre-filter datetime on insert / update

Along the lines of these questions:
'datetime2' error when using entity framework in VS 2010 .net 4.0
How to fix the datetime2 out-of-range conversion error using DbContext and SetInitializer?
I am attempting to use code first to generate a database based on models that I do not own. I.E. I can not modify the models. (I am bringing a desktop application up to speed with a server application.)
I understand that the DateTime value in C# has an invalid MinDate when converting to SqlDateTime. Furthermore, the SQL Express instance created from Entity Framework does not support datetime2. I've tried to apply a filter with default values using a convention:
this.Properties<DateTime>()
.Configure(o => o.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed).HasColumnAnnotation("SqlDefaultValue", "GETDATE()"));
However, when I do this, I get the error Cannot insert the value NULL into column 'CreatedDate', table 'blahblahblah.Companies'; column does not allow nulls. INSERT fails.
I'm not sure I understand that error message as the values are never null. But I'm guessing because the DatabaseGeneratedOption is computed, the value isn't being set.
So far, none of these options has worked for the date time. If there is a way to prefilter inserts and updates, I could run a check on the datetime values and set their values to the SqlDateTime min value. However, my Google foo isn't returning any results for that type of operation. If there is no way to do this, I may just make a helper function that uses reflection to auto adjust all datetime objects appropriately.
I ended up writing a helper function to pre-update datetime values.
public static class DateTimeSwitch
{
public static void DateTimeToSqlDateTime(this object obj)
{
Type objType = obj.GetType();
if (typeof(IEnumerable).IsAssignableFrom(objType))
{
IEnumerable enumerable = (IEnumerable)obj;
if (enumerable != null)
{
foreach (object c in enumerable)
{
if (c != null)
c.DateTimeToSqlDateTime();
}
}
}
else
{
PropertyInfo[] properties = objType.GetProperties();
foreach (PropertyInfo property in properties)
{
if (typeof(DateTime).IsAssignableFrom(property.PropertyType))
{
// Get the value, adjust it.
DateTime value = (DateTime)property.GetValue(obj, null);
if (value < (DateTime)SqlDateTime.MinValue)
{
property.SetValue(obj, (DateTime)SqlDateTime.MinValue, null);
}
}
else if (!property.PropertyType.IsPrimitive && typeof(String) != property.PropertyType && typeof(IEnumerable).IsAssignableFrom(property.PropertyType))
{
IEnumerable enumerable = (IEnumerable)property.GetValue(obj, null);
if (enumerable != null)
{
foreach (object c in enumerable)
{
if (c != null)
c.DateTimeToSqlDateTime();
}
}
}
else if (!property.PropertyType.IsPrimitive)
{
if (property.PropertyType.Assembly == objType.Assembly)
{
var value = property.GetValue(obj, null);
if (value != null) value.DateTimeToSqlDateTime();
}
}
}
}
}
}

Using a variable for a LINQ property

I want to pass a property into a method and search for records that match the given value. The following code does not throw an error, but also does not return any data - ever. I don't know if the problem is setting the column / property like this, or if something else is wrong... the code looks like:
public virtual IList<ReceivingInspection> GetRecordsBySupplier(string property, string value) {
if (property.Length < 1 || value.Length < 1) return null;
var result = from ri in _receiveInspectRepository.Table
where ri.property == value
select ri;
return result.ToList();
}
You should iterate over the items in _receiveInspectRepository.Table and use Reflection to get the value of the property
Something like this:
Type t = ri.GetType();
PropertyInfo prop = t.GetProperty(property);
if(prop.GetValue(ri) == value)
{
dostuff();
}

How to safely check if a dynamic object has a field or not

I'm looping through a property on a dynamic object looking for a field, except I can't figure out how to safely evaluate if it exists or not without throwing an exception.
foreach (dynamic item in routes_list["mychoices"])
{
// these fields may or may not exist
int strProductId = item["selectedProductId"];
string strProductId = item["selectedProductCode"];
}
using reflection is better than try-catch, so this is the function i use :
public static bool doesPropertyExist(dynamic obj, string property)
{
return ((Type)obj.GetType()).GetProperties().Where(p => p.Name.Equals(property)).Any();
}
then..
if (doesPropertyExist(myDynamicObject, "myProperty")){
// ...
}
This is gonna be simple. Set a condition which checks the value is null or empty. If the value is present, then assign the value to the respective datatype.
foreach (dynamic item in routes_list["mychoices"])
{
// these fields may or may not exist
if (item["selectedProductId"] != "")
{
int strProductId = item["selectedProductId"];
}
if (item["selectedProductCode"] != null && item["selectedProductCode"] != "")
{
string strProductId = item["selectedProductCode"];
}
}
You need to surround your dynamic variable with a try catch, nothing else is the better way in makking it safe.
try
{
dynamic testData = ReturnDynamic();
var name = testData.Name;
// do more stuff
}
catch (RuntimeBinderException)
{
// MyProperty doesn't exist
}

How to check if a reflected type is an array

I'm using reflection to read in an xml file and keep coming across an error telling me that I cannot convert a string to a string[] (which I don't want to do!) I think the cause of my problem is I'm unable to tell if the type of the object is an array or not. Below is what I'm currently using (doesn't work right) but I've also tried to use if(mi[i].GetType() == typeof(string[])) which also doesnt work..
MemberInfo[] mi = objType.GetProperties();
for (int i = 0; i < mi.Length; i++)
{
if (mi[i].GetType().IsArray)
{
}
else
{
//Code path is running through here
}
The file is read in correctly..
EDIT: I thought I'd better add the structure to my objType to better explain..
objType is a class that contains a string[] variable that in this case is referred to as mi[i]
You need to use PropertyType rather than GetType() on the MemberInfo to get the underlying type of the property.
var mi = objType.GetProperties();
for (int i = 0; i < mi.Length; i++)
{
var type = mi[i].PropertyType;
//Check for string array
if (type.IsArray && type.GetElementType() == typeof(string))
{
}
}
Or you can do
if(type == typeof(string[]))
{
}

Categories

Resources