Entity framework with Linq - c#

I have following method. I need to return var tynames by method so what would be the return type of the method will it be List<string> or something else and also what is the use of FirstOrDefault().
Thanks in advance for your reply
public static List<string> AppType()
{
var context = new Dll_IssueTracking.IssuTrackingEntities();// Object context defined in Dll_IssuTracking DLL
var query = from c in context.ApplicationTypes//Query to find TypeNames
select new { c.TypeName };
var **TypeNames** = query.FirstOrDefault();
}

FirstOrDefault returns the first element found, or the default value (which is null in this case) if the query returned no results.
In this case the return value of the method should be ApplicationType:
public static ApplicationType AppType()
{
var context = new Dll_IssueTracking.IssuTrackingEntities(); // Object context defined in Dll_IssuTracking DLL
var query = from c in context.ApplicationTypes //Query to find TypeNames
select new { c.TypeName };
return query.FirstOrDefault();
}

FirstOrDefault return first element in sequence, in this sample ApplicationTypes is your sequence or a default value if the sequence contains no elements.

FirstOrDefault is an extension method which looks something like this:
public T FirstOrDefault>T>(this IEnumerable<T> query)
{
return query.Any() ? query.First() : default(T);
}
So, it returns the first element in the sequence if it is not empty, or the default of the type if the sequence is empty.
For Instance, if you have an Enumerable<LinqEntity>, then most likely default(LinqEntity) is null. If you had something like Enumerable<int> then default(int) is 0.

Related

Dynamic lambda expression for where clause

I have a dynamic list of objects on which I am using lambda expression where clause to filter items. For example, just consider that it have 3 properties, foo, bar and baz
class item // let this be current class in dynamic item list
{
bool foo;
string bar;
string baz;
}
Now if I want to filter item list where foo is false I can use following expression
var filtered = itemList.Where("!foo");
I can even filter the list by strings value as
var filtered = itemList.Where("bar==\"value\""); \\all items with bar = value
What I want to actually check is if item in list have a specific string value not null of white space. I tried following code
var filtered = itemList.Where("!String.IsNullOrWhiteSpace(baz)");
It threw an error
Expression of type 'System.Func`2[DynamicType,System.Object]' cannot
be used for parameter of type 'System.String' of method 'Boolean
IsNullOrWhiteSpace(System.String)'
Though I succeeded to get result by following query
var filtered = itemList.Where("baz!=null && baz!=\"\"");
I wanted to confirm if there is a way I can use String.IsNullOrWhiteSpace() in this query.
You can replace "!String.IsNullOrWhiteSpace(baz)" with "!(baz == null || baz.Trim() == string.Empty)" and it should work.
Have a look at System.Linq.Dynamic, there is a great example here.
You will alse need to make sure the List<T> is not List<object>, otherwise System.Linq.Dynamic will not be able to find the properties.
Here is a snippet for your example:
void Main()
{
var itemList = new List<dynamic>{ new {foo = true, bar = "a", baz = "b" }, new {foo = true, bar = (string)null, baz = "d" } };
var filtered = itemList.ToAnonymousList().Where("bar != null and bar !=\"\"");
filtered.Dump();
}
public static class EnumerableEx {
public static IList ToAnonymousList(this IEnumerable enumerable)
{
var enumerator = enumerable.GetEnumerator();
if (!enumerator.MoveNext())
throw new Exception("?? No elements??");
var value = enumerator.Current;
var returnList = (IList) typeof (List<>)
.MakeGenericType(value.GetType())
.GetConstructor(Type.EmptyTypes)
.Invoke(null);
returnList.Add(value);
while (enumerator.MoveNext())
returnList.Add(enumerator.Current);
return returnList;
}
}
I have no problem using your expression - it works fine.
I have used this with objects and entities against an EF storage.
Expression of type 'System.Func`2[DynamicType,System.Object]' cannot
be used for parameter of type 'System.String' of method 'Boolean
IsNullOrWhiteSpace(System.String)'
So looking at the error, it is stating (moving the order around):
The method IsNullOrWhiteSpace, that returns a Boolean, expects a parameter of type System.String.
But what was received was Expression of type System.Func``2[DynamicType,System.Object]'
It appears that you may have referenced an object rather than a string value for your comparison. However, without sample code for the objects you are using, and whether you are using objects, entities, or LinQ to SQL (which I haven't tried) we can only guess at what you have supplied for the expression.
Finally, what is a
'dynamic item list'?
Are you using Dynamic, or is it a normal List<Item>?

c# - Using input parameter of lambda expression in if statement

I have if statement like this:
if (myList.Any(x => s.Contains(x))
{
//some code here
}
in which I check if there is a string in myList which is contained in a string s.
Is it somehow possible to get the element x of this list and use it in the if statement showed above (in "//some code here" part), when the condition is met?
Thank you.
Switch from Any to FirstOrDefault, that will return the item that matched the test or null if no item was matched.
var found = myList.FirstOrDefault(x => s.Contains(x));
if (found != null)
{
//some code here
}
If null could be considered a "valid value" for a element in myList you can create a extension method TryFirst
public static class ExtensionMethods
{
public static bool TryFirst<T>(this IEnumerable<T> #this, Func<T, bool> predicate, out T result)
{
foreach (var item in #this)
{
if (predicate(item))
{
result = item;
return true;
}
}
result = default(T);
return false;
}
}
This would let you do
string foundString;
var wasFound = myList.TryFirst(x => s.Contains(x), out foundString);
if (wasFound)
{
//some code here
}
and tell the difference between a null in your list and a default result.
The above two methods only act on the first item on the list that the Contains will match, if you want to act on all the items use a Where( clause and a foreach
foreach(var item in myList.Where(x => s.Contains(x))
{
//some code here
}
You must promise you will not use the following code and use one of the other options first
You can also do your stated question, it is possible to get a variable assigned to inside lambada. However this can not be done with expression lambadas, only with statement lambadas.
string matachedString = null;
if (myList.Any(x => { var found = s.Contains(x);
if(found)
matachedString = x;
return found;
});
{
//some code here
}
But only do this option as a last resort, use one of the more appropriate methods like FirstOrDefaut or write a custom method like TryFirst first.
I'd use foreach/Where()for this, even if I'm only expecting 0 or 1 result:
foreach (var item in myList.Where(x => s.Contains(x)))
{
//some code here
}

Linq syntax error in ASP MVC controller method

I have a Linq query I need to use in my Index method in the page's controller, however I am getting the following error on the "select new" portion of the code:
Error
Cannot implicitly convert type 'System.Linq.IQueryable<AnonymousType#1>' to 'string'
Action method
public ActionResult Index(string query)
{
var agentProductTraining = "";
if (String.IsNullOrEmpty(query))
{
BlankIndex();
}
else
{
agentProductTraining = from course in db.Course
where
course.CourseDescription.Contains(query)
select new
{
course.CourseCode,
course.CourseDescription,
course.Partner,
course.Status,
course.LastChangeDate,
course.LastChangeOperator
};
}
return View(agentProductTraining.ToList());
}
As the error clearly states, you cannot assign the result of a LINQ query (IQueryable<T>) to a variable of type string.
You should declare the variable in that line:
var agentProductTraining = select ...
You've initialized the variable as a string, so the compiler makes the variable a string type (since you've user the var keyword), but then tried to assign a collection of anonymous types to it.
You can declare it as an object instead or var:
object agentProductTraining; // can safely be overwritten
Also I assume you mean:
return BlankIndex();
in the if block. Otherwise it will fall through to
return View(agentProductTraining.ToList());
where agentProductTraining is going to be null
Of course if you use return BlankIndex in the if block you can simplify the whole thing:
if (String.IsNullOrEmpty(query))
{
return BlankIndex();
}
// don't need an `else` here since the if will return to the caller
var agentProductTraining = from course in db.Course
where
course.CourseDescription.Contains(query)
select new
{
course.CourseCode,
course.CourseDescription,
course.Partner,
course.Status,
course.LastChangeDate,
course.LastChangeOperator
};
return View(agentProductTraining.ToList());

LINQ c# unique element in collection

I have a method that is supposed to check whether there is exactly one element in a collection that holds true for some predicate (given as a Func).
public bool ExistsUnique(Func<T, bool> p)
{
var tempCol = from i in MyCollection where p(i) select i;
return (tempCol.Count() == 1);
}
The problem with this is that when a second element that also holds true for the predicate
is found (for example two of the same string exists in a collection) the count is still 1. Which means it either overrides the first element or never adds the second because it already exists.
Any ideas as to how I can fix this method?
thx
/Peter
You can use the Single() method provided by LINQ like this:
public bool ExistsUnique(Func<T, bool> p)
{
try
{
var temp = myCollection.Single(x => p(x));
}
catch(Exception e)
{
// log exception
return false;
}
return true;
}
"Returns the only element of a sequence that satisfies a specified condition, and throws
an exception if more than one such element exists."
From http://msdn.microsoft.com/en-us/library/bb535118.aspx
EDIT
To avoid throwing an exception, you may also use the SingleOrDefault() method:
public bool ExistsUnique(Func<T, bool> p)
{
return myCollection.SingleOrDefault(x => p(x)) != null;
}
There must be some other problem. I'd suspect your predicate. For example, this returns a count of 2, as expected:
List<string> MyCollection = new List<string>()
{
"hello",
"hello"
};
var tempCol = from i in MyCollection where i == "hello" select i;
int count = tempCol.Count();
I doubt that it's the way you're calling it, either. The following works (returns false):
static List<string> MyCollection = new List<string>()
{
"hello",
"hello"
};
static bool ExistsUnique(Func<string, bool> p)
{
var tempCol = from i in MyCollection where p(i) select i;
return tempCol.Count() == 1;
}
static void DoIt()
{
bool isUnique = ExistsUnique((s) => s.Equals("hello"));
Console.WriteLine(isUnique);
}
Are you sure tempCol has looped completely through MyCollection?
is Count() a method that forces the complete loop or is it lazy?
Does for example tempCol.ToList().Count give the correct result?
This implementation would make it so you don't have to actually enumerate the entire collection, so will save you some execution time.
public bool ExistsUnique(Func<T, bool> p)
{
return MyCollection.Where(i => p(i)).Take(2).Count() == 1;
}
The Take(2) limits the Count to only enumerate the first two meeting the criteria.

Initialize var to null

I have seen how to initialize var to null. This does not help in my situation. I have
string nuller = null;
var firstModel = nuller;
if(contextSelectResult.Count() > 0)
firstModel = contextSelectResult.First();
I get error
Cannot implicitly convert type
'SomeNamespace.Model.tableName' to 'string'.
I am trying to avoid try/catching InvalidOperation for First() when no first exists as its expensive. So, how can I get past the scope issue here?
You can try this:
var firstModel=(dynamic) null;
You can use FirstOrDefault() instead.
firstModel = contextSelectResult.FirstOrDefault();
if(firstModel != null)
{
...
}
Simply use FirstOrDefault() instead. The whole point of FirstOrDefault is to return the first element of the sequence if it exists, or the default value of the element type (i.e. null for all reference types) otherwise.
Note that in other cases where you wish to check for the existence of any elements, using Any() can sometimes be more efficient than Count() > 0 - it depends on the exact context, but IMO it's a simpler way of expressing what you're looking for anyway.
Try FirstOrDefault instead. It returns nullby default if there is no item.
Please Try this option:
var var_name = (dynamic)null;
or
var var_name = (Type*)null;
Type* : eg --> string, var, int
If there is no First it'll be a null for reference types:
var firstModel = contextSelectResult.FirstOrDefault();
You can use the generic for this case also
public static dynamic GetTheListOfDevicesDependOnDB(int projectID)
{
List<Devices_Settings> ListDevices_Settings = new List<Devices_Settings>();
var db = new First_DataContext();
var devices = (dynamic) null;
switch (projectID)
{
case (int)enmProjectType.First:
db = new First_DataContext();
devices = db.Device_Fisrt.ToList();
break;
case (int)enmProjectType.Second:
var db1 = new Second_DataContext();
devices = db1.Device_Second.ToList();
break;
default:
break;
}
foreach (var item in devices)
{
//TODO
}
return ListDevices_Settings;
}

Categories