Get ICollection property of generic type - c#

I'm new in ASP.NET MVC 5, I need get the Icollection property and search into other property, if printed the result of the first search is fine, but when i go to search in the result is null.
what is the problem?
var userId = User.Identity.GetUserId();
var user = db.Users.Include( u=> u.Sucursales)
.Where(u => u.Id == userId)
.SingleOrDefault();
if( user != null )
{
var sucursal = user.Sucursales.Include(s => s.Emisor)
.Where(s => s.ID == suc)
.SingleOrDefault();
if (sucursal != null)
{
var tipoCfe = sucursal.Emisor.TiposCfe
.Where(t => t.ID == factura)
.SingleOrDefault();

Your query will take place right away since you are using SingleOrDefault(), see this StackOverflow question pertaining to SingleOrDefault() Your Include(s => s.Emisor) sticks out to me though. Since Emisor wasn't included when fetching the user, you will not be able to request that since your query is no longer of type IQueryable. Your query has already been executed.
In order to retrieve the data you require, you will have to obtain the data during your first query. I would do something similar to: db.Users.Include("Sucursales.Emisor") when you retrieve the user.
More on include method... MSDN Explanation of Include Method

I changed
var user = db.Users.Include( u=> u.Sucursales)
for
var user = db.Users.Include("Sucursales.Emisor")

Related

Using LINQ to populate a string with a single column value

I'm a newbie both to C# and to LINQ and would appreciate a small push in the right direction.
Firstly, I have an Overrides SQL table (and a corresponding EF DB context), which has a Type, Value, and Override Value. The idea is that for a particular kind ("Type") of override, the code can check a particular value and go see if there is an override value that should be used instead.
var branchOverrides = overridesSqlContext.Overrides
.Where(q => q.Type == "Branch Override")
.Select(s => new
{
s.Value,
s.OverrideValue
});
In this case, I want the list of different override values of the "Branch Override" type. From there, I would like to be able to retrieve a specific override value at a given point within my code. How can I query the branchOverrides variable I've created to be able to say something like:
string readingOverride = select OverrideValue from branchOverrides where Value = "Reading"
My code will need to be able to read various override values for different branches at different points, and being able to query the branchOverrides variable at any point would seem like the ideal approach.
Thank you for any assistance on this.
You can use Single() on the query object you have:
string readingOverride = branchOverrides
.Single(bo => bo.Value == "Reading")
.OverrideValue;
This will throw an exception if an entry doesn't exist though so you probably want to use SingleOrDefault instead and check for a null return.
Also note that the branchOverrides object here is an IQueryable<> which means that every time you use it, it will send a query to the database. You may want to materialise that to a local list by adding .ToList() after the Select(...). Alternatively, you may want to look at caching this data, especially if it's going to be used frequently.
If I understood you right, you want the entry with Value = "Reading" and Type="Branch Override":
var branchOverride = overridesSqlContext.Overrides
.SingleOrdDefault(q => q.Type == "Branch Override"
&& q.Value == "Reading")
.Select(s => new
{
s.Value,
s.OverrideValue
});
if (branchOverride != null)
{
// do whatever ...
}
For performance issue is good to put .ToList() in the end of your LINQ expression if you need to iterante over that list too many times.
var branchOverrides = overridesSqlContext.Overrides
.Where(q => q.Type == "Branch Override")
.Select(s => new
{
s.Value,
s.OverrideValue
}).ToList();
If it you will load the entire list into the memory avoiding to execute the sql query to fetch the data if you need to iterate through your list.
Other thing that you can do is:
string readingOverride = string.Empty;
var branchOverride = branchOverrides.FirstOrDefault(x => x.Value == "Reading");
if(branchOverride != null)
{
readingOverride = branchOverride.OverrideValue;
}
Hope that helps.
If Value is unique within "Branch Override" perhaps you want to turn it to a dictionary for fast lookup
var branchOverrides = overridesSqlContext.Overrides
.Where(q => q.Type == "Branch Override")
.Select(s => new
{
s.Value,
s.OverrideValue
})
.ToDictionary(k => k.Value, v => v.OverrideValue);
Then later on you can find the override value quickly and efficiently
var readingOverride = branchOverrides["Reading"];

Filtering Related Entites with Entity Framework

According to this StackOverflow answer:
Linq to Entities - how to filter on child entities
you should be able to filter down the list of related entities in Entity Framework by utilizing a projection, like I've done here:
Company company = _context.Company
.Where(g => g.CompanyId == id)
.Select(comp => new
{
group = comp,
operators = comp.Operator,
formFamilies = comp.FormFamily.Where(ff => ff.IsActive ?? false)
}).AsEnumerable().Select(i => i.group).FirstOrDefault();
To give a quick overview of what I'm trying to obtain here, I'm trying to get a list of all of the active form families associated with this company object, however, whenever I restrict the results in any way, the result set is empty.
If the line were formFamilies = comp.FormFamily then it returns two results, one active one inactive
If the line is formFamilies = comp.FormFamily.Where(ff => true) then it returns nothing
If the line is formFamilies = comp.FormFamily.OrderBy(ff => ff.FormFamilyId) then it returns nothing.
Any sort of modification that I do to comp.FormFamily means the result set returns nothing, I've dug through the deepest sections of SA to try to find a solution, and tried every solution I've found, but nothing seems to cause this list to return anything.
Assuming that Company and FormFamily entities has one to many relationship I would suggest to use a join statement.Something like this should give you what you are looking for.
var company = from c in _context.Company
join f in _context.FormFamily
on c.Id equals f.CompanyId
where c.Id == id
select new Company()
{
Id = c.Id,
operators = c.Operator.ToList(),
formFamilies = c.FormFamily.Where(x=>x.IsActive ==
false).ToList()
} .FirstOrDefault();
Hope this helps.
I didn't quite understand what is your query is supposed to do. But it seems to me that you cannot just call Select method on another Select result method.
Anyway, you could simply use Include methods instead of projecting.
var company = _context.Company
.Where(c => c.Id == id)
.Include(c => c.FormFamily).Where(ff => ff.IsActive ?? false)
.ToList();
Did not test it. To prove it works or not be sure put an entity model in the question. Then I may produce more accurate answer.

LINQ to Entities does not recognize the method "GetUserById"

I've tried to do this (load some data from a db to send it by JSON)
But I've catched an excpetion:
Additional information: LINQ to Entities does not recognize the method
'Model.Models.User GetUserById(Int32)' method, and this method cannot
be translated into a store expression
How can I avoid this exception and get the userId which I needed for the each record
Entity Framework tries to convert your query into SQL query. But it fails to convert GetUserById method call into SQL (no surprise here). You should move this part of linq query to client side:
var favList = context.FavoriteMessages
.Where(m => m.UserId == user.UserId && m.OnlineRoomId == user.OnlineRoomId)
.Select(m => new {
m.UserId, // return user id from database
m.Instance,
m.CreatedOn
})
.AsEnumerable() // further part of query is not translated into SQL
.Select(i => new {
UserName = userService.GetUserById(i.UserId).Name, // get name locally
i.Instance,
i.CreatedOn
}).ToList();
But if you'll think about filtering part of your query, you'll see that you are selecting only messages which have userId equal to user.UserId. That means - all of selected messages will have same user id, and what is more important - that will be id of user which you already have. And even more - you already have name of user in User.Identity.Name. So, the query should look like:
var user = userService.GetUserByName(User.Identity.Name);
var favorites = from m in context.FavoriteMessages
where m.UserId == user.UserId && m.OnlineRoomId == user.OnlineRoomId
select new {
UserName = user.Name,
m.Instance,
m.CreatedOn
};
return Json(favorites.ToList(), JsonRequestBehavior.AllowGet);

Why does Select return a boolean?

I'm working with Entity Framework 6 in MVC 5.
I have the following method:
[HttpPost]
public ActionResult UpdateDetails(ApplicationUser applicationUser)
{
var context = new ApplicationDbContext();
var user = context.Users.Select(x => x.UserName == applicationUser.UserName).FirstOrDefault();
//etc etc
}
Users is an IDbSet<ApplicationUser>.
Why am I getting a bool back from the Select method?
My expectation would be to get an ApplicationUser object back. Why isn't this the case?
Thanks
Select() projects an element of a sequence. Since x.UserName == applicationUser.UserName returns a bool, the result of the method will be a boolean.
What you want requires the Where method. This filters the sequence based on the specified predicate:
var user = context.Users.Where(x => x.UserName == applicationUser.UserName).FirstOrDefault();
Which can be shortened to:
var user = context.Users.FirstOrDefault(x => x.UserName == applicationUser.UserName);
This is possible, since this overload of FirstOrDefault() takes a filter predicate as second parameter.
Your select is returning an object that is the result of the comparison.
Change to:
var user = context.Users.FirstOrDefault(x => x.UserName == applicationUser.UserName);
It is because you are SELECTing a boolean.
Since there is no requirement specified, I am guessing your requirement from your attempted code.
use the below line.
var user=context.Users.Where(user=>user.UserName==applicationUser.UserName).FirstOrDefault();
Select literally selects something inside the arguments. So, if you have an expression that returns a bool, Select will return bool.

Multiple Include and Where Clauses Linq

I have a database where I'm wanting to return a list of Clients.
These clients have a list of FamilyNames.
I started with this
var query = DbContext.Clients.Include(c => c.FamilyNames).ToList() //returns all clients, including their FamilyNames...Great.
But I want somebody to be able to search for a FamilyName, ifany results are returned, then show the clients to the user.
so I did this...
var query = DbContext.Clients.Include(c => c.FamilyNames.Where(fn => fn.familyName == textEnteredByUser)).ToList();
I tried...
var query = DbContext.Clients.Include(c => c.FamilyNames.Any(fn => fn.familyName == textEnteredByUser)).ToList();
and...
var query = DbContext.FamilyNames.Include(c => c.Clients).where(fn => fn.familyname == textEnteredByUser.Select(c => c.Clients)).ToList();
What I would like to know (obviously!) is how I could get this to work, but I would like it if at all possible to be done in one query to the database. Even if somebody can point me in the correct direction.
Kind regards
In Linq to Entities you can navigate on properties and they will be transformed to join statements.
This will return a list of clients.
var query = DbContext.Clients.Where(c => c.FamilyNames.Any(fn => fn == textEnteredByUser)).ToList();
If you want to include all their family names with eager loading, this should work:
var query = DbContext.Clients.Where(c => c.FamilyNames.Any(fn => fn == textEnteredByUser)).Include(c => c.FamilyNames).ToList();
Here is some reference about loading related entities if something doesn't work as expected.
You can use 'Projection', basically you select just the fields you want from any level into a new object, possibly anonymous.
var query = DbContext.Clients
.Where(c => c.FamilyNames.Any(fn => fn == textEnteredByUser))
// only calls that can be converted to SQL safely here
.Select(c => new {
ClientName = c.Name,
FamilyNames = c.FamilyNames
})
// force the query to be materialized so we can safely do other transforms
.ToList()
// convert the anon class to what we need
.Select(anon => new ClientViewModel() {
ClientName = anon.ClientName,
// convert IEnumerable<string> to List<string>
FamilyNames = anon.FamilyNames.ToList()
});
That creates an anonymous class with just those two properties, then forces the query to run, then performs a 2nd projection into a ViewModel class.
Usually I would be selecting into a ViewModel for passing to the UI, limiting it to just the bare minimum number of fields that the UI needs. Your needs may vary.

Categories