LINQ Checking for Nulls - asp.net-mvc

How do I check Nulls in Linq?
I have a third-party code that returns a DataTable with a column type DateTime that is nullable.
My code:
var profile = (from d in ds.Tables[0].AsEnumerable()
select new User
{
FirstName = d["FirstName"].ToString(),
Birthdate = Convert.ToDateTime(d["BirthDate"].ToString())
}).FirstOrDefault();
returns an error that the Object cannot be cast from DBNull to other types on the Birthdate= statement.
I tried using the following code but returns a cast exception (Cannot cast from string to DateTime?)
Birthdate = (DateTime?)d["BirthDate"].ToString();
Is there a way to short-hand checking the null values?

I have not tested this, but you can try the following:
Birthdate = d.Field<DateTime?>("BirthDate")
From MSDN:
The Field method provides support for accessing columns as nullable types. If the underlying value in the DataSet is [DBNull.]Value, the returned nullable type will have a value of null.

You can create a helper function to check the value for DBNull, as follows:
private static DateTime? ConvertNullableToDateTime(object val) {
return (val != null && val != DBNull.Value) ? Convert.ToDateTime(val.ToString()) : null;
}
Now you can use this method in your LINQ query:
var profile = (from d in ds.Tables[0].AsEnumerable()
select new User
{
FirstName = d["FirstName"].ToString(),
Birthdate = ConvertNullableToDateTime(d["BirthDate"])
}).FirstOrDefault();

I have got error while I used the above code. I think we can use the below code.
Birthdate = dr["BirthDate"] == DBNull.Value ? (DateTime?)null : (DateTime)dr["BirthDate"];
If we use Convert.ToString(dr["BirthDate"]), then it convert to empty string, if it has DBNull.
Try that also.

Related

Entity Framework: Select field name causing error

The moment I mention field names when fetching data from db, I start getting errors.
Before my code was this and it was working:
var customer = from s in db.Customers
select s;
The moment I change it to:
var customer = (from s in db.Customers
select new
{
CompanyName = s.CompanyName,
ContactName = s.ContactName,
ContactTitle = s.ContactTitle,
Address = s.Address,
});
I start getting error as follows:
The model item passed into the dictionary is of type
'PagedList.PagedList1[<>f__AnonymousType24[System.String,System.String,System.String,System.String]]',
but this dictionary requires a model item of type
'PagedList.IPagedList`1[MVCCRUDPageList.Models.Customer]'.
My view looks like:
#model PagedList.IPagedList<MVCCRUDPageList.Models.Customer>
#using PagedList.Mvc;
This error is caused because you are not sending the Customer model to the view.
By doing select new { ... } you are creating an anonymous object.
You may consider changing your code to:
select new MVCCRUDPageList.Models.Customer
{
CompanyName = s.CompanyName,
ContactName = s.ContactName,
ContactTitle = s.ContactTitle,
Address = s.Address,
}
You may still need to convert the IQueryable to IPagedList
The error is telling you that the view is expecting one type but you are passing it another type. The Linq Select method you have is projecting to an anonymous type instead of the expected Customer class. Change your code to match, something like this
var customer = (from s in db.Customers
select new Customer //<--- This here, you may need to use
// the full namespace MVCCRUDPageList.Models
{
CompanyName = s.CompanyName,
ContactName = s.ContactName,
ContactTitle = s.ContactTitle,
Address = s.Address,
});

C# Reflection PropertyInfo Nested Classes in MVC

Is there a generic way to retrieve PropertyInfo based on a string value alone, when deeper than one level.
I assume this is probably simple enough, but my search results are only as good as my search criteria, and I think I am having an issue articulating the proper keywords to get search results for what I am after.
I would like to be able to do something like the following (which works perfect if the key is for a direct property / one level - ie key = 'firstName'):
public static PropertyInfo (this HtmlHelper htmlHelper, string key) {
PropertyInfo pInfo = htmlHelper.ViewData.Model.GetType().GetProperty(key);
return pInfo;
}
But is there a way for me to return the PropertyInfo based on a string alone
when Key equals something more complex, such as nested classes, objects, lists, etc...:
key = "somelist[0].myproperty"
key = "Items[0].someotherlist[1].someproperty" (where Items is defined as List<Item> Items {get; set;}, someotherlist is defined similarly)
Can the method be generic enough to essentially drill down as many levels as needed (defined)?
So here is what I came up with... this is about to get wordy, and mostly 'stream of thought'
I have custom HtmlHelperExtension, and within it :
PropertyInfo[] pInfoArray = htmlHelper.ViewData.Model.GetType().GetProperties();
PropertyInfo pInfo = GetPropertyInfo(pInfoArray, key);
This GetPropertyInfo() method takes the key, and the PropertyInfo array, cycles through the properties, until the keypart (using regex to remove any indication of an array from the string, so I am left with only the property) matches the property name. On Match, determine if this is the first cycle in the loop, and if so assign the matched property to my Temp Type and PropertyInfo variables. If keyParts are remaining to loop through, subsequent loops now use previously set temp variables and the for loop index [i] to iterate / drill down the class structure. Each time setting the pInfoTemp variable, and then pTypeTemp so the next loop can use where it left off.
private static PropertyInfo GetPropertyInfo(PropertyInfo[] pInfoArray, string key)
{
PropertyInfo pInfo = null;
string[] keyParts = key.Split('.');
Regex arrayRgx = new Regex("\\[\\d*\\]");
PropertyInfo pInfoTemp = null;
Type pTypeTemp = null;
foreach (PropertyInfo prop in pInfoArray)
{
string keyPartsTrimmed = arrayRgx.Replace(keyParts[0], ""); // removes '[#]' from string
if (keyPartsTrimmed == prop.Name) // match property name
{
for (int i = 0; i < keyParts.Count(); i++)
{
if (i == 0) // initial item [0]
{
pTypeTemp = prop.PropertyType; // gets [0]'s type
pInfoTemp = prop; // assigns [0]'s property info
}
else
{
pInfoTemp = GetNestedPropertyInfo(pTypeTemp, arrayRgx.Replace(keyParts[i], "")); // gets [i]'s property info for return or next iteration
pTypeTemp = pInfoTemp.PropertyType; // gets [i]'s type for next iteration
}
}
pInfo = pInfoTemp;
break;
}
}
return pInfo;
}
This next method is invoked by the previous for grabbing nested property info, more importantly for detecting whether the passedItemType is a List (without this, it fails to work correctly as it is unable to find the property asked for in a List<> Type. I need to know what the List item Type is.
private static PropertyInfo GetNestedPropertyInfo(Type passedItemType, string passedProperty)
{
PropertyInfo pInfoOut = null;
if (passedItemType.IsGenericType && passedItemType.GetGenericTypeDefinition() == typeof(List<>))
{
Type itemType = passedItemType.GetGenericArguments()[0];
pInfoOut = itemType.GetProperty(passedProperty);
}
else
{
pInfoOut = passedItemType.GetProperty(passedProperty);
}
return pInfoOut;
}
This currently suits my requirements as they are today, and I have tested it with the following properties, lists, subclasses, subclasses with lists, etc.. to 4 levels deep, but should function properly no matter the depth:
firstName
lastName
Items[1].sprocket
subClass.subClassInt
subClass.mySubClassObj.sprocketObj
subClass.ItemsInMySubClass[1].sprocket
subClass.ItemsInMySubClass[0].mySubClassObj.widgetObj
subClass.ItemsInMySubClass[2].mySubClassObj.sprocketObj
If anyone has a better solution, or see any potential issues with what I have, I welcome the feedback.
The best way in your case is to make a parser that split that expression.

#Html.DisplayFor for Empty

I am trying to display empty string when model.EndDate is 0
#Html.DisplayFor(modelItem => model.EndDate)
I tried
#Html.DisplayFor(modelItem => model.EndDate == 0 ? "" : model.EndDate.ToString())
and
#Html.Display("End Date",model.EndDate == 0 ? "" : model.EndDate.ToString())
both did not worked for me. Both of the displaying empty when data is available.
Do a conditional outside the DisplayFor:
#if (Model.EndDate != 0)
{
Html.DisplayFor(modelItem => model.EndDate)
}
You can't compare a datetime to 0 in asp.net.
error CS0019: Operator `==' cannot be applied to operands of type `System.DateTime' and `int'
A DateTime is a value type so it get a default value of DateTime.MinValue when it isn't set.
using System;
public class Test {
public static DateTime badDate;
public static DateTime goodDate = DateTime.Now;
public static void Main(string[] args) {
Console.WriteLine(goodDate == DateTime.MinValue ? "" : goodDate.ToString());
Console.WriteLine(badDate == DateTime.MinValue ? "" : badDate.ToString());
}
}
How about this one ?
DateTime dt;
if (DateTime.TryParse("Your Date", out dt))
{
//Now you have validated the date
//Your code goes here
}
I think you should make your model property be a nullable type. So for example if its type is DateTime then declare the property as a nullable DateTime:
public DateTime? EndDate { get; set; }
this way instead of a 0 date (whatever that means) you will have no value. This also makes sense especially if this model property is coming from the database and is nullable.
You can read more about the nullable types here: http://msdn.microsoft.com/en-us/library/2cf62fcy(v=vs.80).aspx
I didn't like the answers given above because adding IF Statements to everything just slows your system down, in my case i needed to display a default string value several times in each row of a list view when the class property was a null value.
So have a look at the MS Docs here:
DisplayFormatAttribute.NullDisplayText Property
The following example shows how to use the NullDisplayText to define a caption to display when the data field is null.
// Display the text [Null] when the data field is empty.
// Also, convert empty string to null for storing.
[DisplayFormat(ConvertEmptyStringToNull = true, NullDisplayText = "[Null]")]
public object Size;

Dart: How to bind to variables annotated with int via Web UI?

What is the best practice in Dart when dealing with classes as data records?
To Elaborate: When writing an app, it is likely that a class for a table row will be created. As in
class Item { int itemid, String itemName, double score }
Item item = new Item();
This allows compile time catching of any typos etc. in Dart. (Unlike using a class that relies on NoSuchMethod.)
It will also need a corresponding string structure to bind to the HTML such as
<input id="itemname" type="text" bind-value="itemEdit.itemName">
So the Dart would be:
class ItemEdit { String itemId, String itemName, String score }
ItemEdit itemEdit = new ItemEdit();
Next we need a way to get from one to the other, so we add a method to Item
fromStrings(ItemEdit ie) {
itemid = ie.itemId == null ? null : int.parse(ie.itemId);
itemName = ie.ItemName;
score = ie.score == null ? null : double.parse(ie.score);
}
And the other way around:
toStrings(ItemEdit ie) {
ie.itemid = itemId == null ? '' : ie.itemId.toString();
ie. itemName = itemName == null ? '' : itemname; // Web_ui objects to nulls
ie.score = score == null ? null : score.toStringAsFixed(2);
}
Also, we get jason data from a database, so we need to add another method to Item:
fromJson(final String j) {
Map v = JSON.parse(j);
itemid = v['itemid'];
itemname = v['itemname'];
score = v['score'];
}
And we need to be able to revert to default values:
setDefaults() { itemId = 0; itemName = "New item"; score = 0; }
This verbosity gets me feeling like I am writing COBOL again!
There is something fundamental missing here - either in my understanding, or in the Dart/WebUI libraries.
What I would like to write is something like
class Item extends DataRecord {
int itemid = 0,
String itemName = 'New item',
double score = 0.0;
}
Then, without further coding, to be able to write code such as
item.toStrings();
...
item.fromStrings();
...
item.fromJson(json);
...
item.setDefaults(); // results in {0,'New item',0.0}
And to be able to write in the HTML:
value="{{item.strings.score}}"
If this was possible, it would be quicker, simpler, clearer, and less error prone than the code I am writing at the moment.
(Full disclosure, this answer is written with the assumption that at least one bug will be fixed. See below)
Three suggestions that might help.
Use named constructors to parse and create objects.
Take advantage of toJson() when encoding to JSON.
Use bind-value-as-number from Web UI
1) Named constructors
import 'dart:json' as json;
class Item {
int itemid;
String itemName;
double score;
Item.fromJson(String json) {
Map data = json.parse(json);
itemid = data['itemid'];
itemName = data['itemName'];
score = data['score'];
}
}
2) Encoding to JSON
The dart:json library has a stringify function to turn an object into a JSON string. If the algorithm encounters an object that is not a string, null, number, boolean, or collection of those, it will call toJson() on that object and expect something that is JSON-encodable.
class Item {
int itemid;
String itemName;
double score;
Map toJson() {
return {'itemid':itemid, 'itemName':itemName, 'score':score};
}
}
3) Now, having said that, sounds like you want to easily bind to HTML fields and get primitive values back, not just strings. Try this:
<input type="number" min="1" bind-value-as-number="myInt" />
(Note, there seems to be a bug with this functionality. See https://github.com/dart-lang/web-ui/issues/317)
(from https://groups.google.com/a/dartlang.org/forum/#!topic/web-ui/8JEAA5OxJOc)
Just found a way to perhaps help a little in the this situation:
class obj {
int gapX;
String get gapXStr => gapX.toString();
set gapXStr(String s) => gapX = int.Parse(s);
...
Now, from the HTML you can use, for example
bind-value="gapXStr"
and in code you can use
x += ob.gapX;

How can I write custom comparison (definition for binary operator Equal) for entityframework object to an int?

I'm getting this error:
ex = {"The binary operator Equal is not defined for the types 'MySite.Domain.DomainModel.EntityFramework.NickName' and 'System.Int32'."}
What I tried to do was do a select all where the NickNameId = someIntPassedIn... the problem is that the NickNameId is a foreign key, so when it compares the someIntPassedIn to the NickNameId it pulls the whole NickName object that the NickNameId refers to and tries to compare the int to that object.
I need a solution here to allow it to compare the int to the NickName object's Id... so
A) How can I define the binary operator Equal for comparing these two objects
OR
B) How can I compare it directly to the id instead of the whole object?
You don't have to read this, but here's the SelectAllByKey method incase it helps: (I passed in "NickNameId" and "1")
public IList<E> SelectAllByKey(string columnName, string key)
{
KeyProperty = columnName;
int id;
Expression rightExpr = null;
if (int.TryParse(key, out id))
{
rightExpr = Expression.Constant(id);
}
else
{
rightExpr = Expression.Constant(key);
}
// First we define the parameter that we are going to use the clause.
var xParam = Expression.Parameter(typeof(E), typeof(E).Name);
MemberExpression leftExpr = MemberExpression.Property(xParam, this._KeyProperty);
int temp;
BinaryExpression binaryExpr = MemberExpression.Equal(leftExpr, rightExpr);
//Create Lambda Expression for the selection
Expression<Func<E, bool>> lambdaExpr = Expression.Lambda<Func<E, bool>>(binaryExpr, new ParameterExpression[] { xParam });
//Searching ....
IList<E> resultCollection = ((IRepository<E, C>)this).SelectAll(new Specification<E>(lambdaExpr));
if (null != resultCollection && resultCollection.Count() > 0)
{
//return valid single result
return resultCollection;
}//end if
return null;
}
Let me know if you need any more info.
Thanks,
Matt
You should call SelectAllByKey('NickName.ID','1').
Since ID is property of property, you could use this extension method:
public static MemberExpression PropertyOfProperty(this Expression expr,string propertyName)
{
var properties = propertyName.Split('.');
MemberExpression expression = null;
foreach (var property in properties)
{
if (expression == null)
expression = Expression.Property(expr, property);
else
expression = Expression.Property(expression, property);
}
return expression;
}
The accepted answer seems way too complicated for the problem at hand, if I'm reading this correctly.
If I understand you correctly, you're trying to run a query like:
var q = from e in Context.SomeEntities
where e.NickNameId == someIntPassedIn
select e;
...but this won't work, because e.NickNameId is an entity, not an integer.
To reference the Id property, you can just refer to it, like this:
var q = from e in Context.SomeEntities
where e.NickNameId.Id == someIntPassedIn
select e;
Update: If you can't use strong-typed properties due to your level of abstraction (per your comment), then use query builder methods:
var q = (ObjectQuery<T>)Repository.SelectSomething();
return q.Where("it.NickName.Id = " + someIntPassedIn.ToString());
You can adapt this as you see fit, but the general point is that the EF already knows how to translate strings to property members.

Resources