RIA Servcies Filter Out Included Entities - linq

Below returns all of the people in a building and all of their computers, and this works.
I want to change this to only include the Computers where Active == 1 and only the ActivityLogs where ActivityTypeId == 5. But if they don’t have either I still want the person returned.
public IQueryable<Person> GetPeople(int BuildingId)
{
return this.ObjectContext.People
.Include("Computers")
.Include("ActivityLog")
.Where(p => p.buildingId == BuildingId && !p.migrated)
.OrderBy(p => p.name);
}

Unfortunately this is not possible using Include syntax. As an alternative, you can select each entity individually like so:
var queryWithAllData = this.ObjectContext
.People
.Select(p => new
{
Person = p,
Computers = p.Computers.Where(c => c.Active == 1),
ActivityLogs = p.ActivityLog.Where(a => a.ActivityTypeId == 5)
});
// Do what you need with the records now that you have all the data.

Related

How can I add Sum from another Table in my Model?

So I have my View setup like this in the controller:
public ActionResult View(Guid projectID)
{
OnboardModel model = context.onboard_projectInfos.Where(x => x.projectID == projectID).Select(x =>
new OnboardModel()
{
propertymanagername = x.propertymanagername,
propertymanagercontactemail = x.propertymanagercontactemail,
date_modified = (DateTime)x.date_modified,
projectmanagercontactnumber = x.projectmanagercontactnumber,
Developer = x.onboard_projectCreate.Developer,
status1 = x.onboard_projectCreate.status1,
ProjectName = x.onboard_projectCreate.ProjectName
}).SingleOrDefault();
var pix = projectID.ToString();
context.onboard_BuildingInfos.Where(x => x.buildprojectID == pix).GroupBy(x => x.buildprojectID).Select(g => {
model.totalres = g.Sum(b => b.numberofres);
model.totalcom = g.Sum(b => b.numberofcommer);
});
return View(model);
}
Problem is grabbing the sum of numberofres and numberofcommer from BuildingInfos.
Using .Select gives me the error:
Error CS0411 The type arguments for method 'Queryable.Select(IQueryable, Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
How to I write this LINQ statement correctly?
Thanks.
You cannot modify an object within a select (you can only create a new object). Further, you can't add new properties to an existing object.
We'll assume that OnboardModel defines the totalres and totalcom properties.
var query = context.onboard_BuildingInfos
.Where(x => x.buildprojectID == pix)
.GroupBy(x => x.buildprojectID);
foreach(var g in query)
{
model.totalres = g.Sum(b => b.numberofres);
model.totalcom = g.Sum(b => b.numberofcommer);
}

(Linq & EF) Where MyType = (int)Enum does not work

I have a database in Azure that I created from scratch (not using code first in EF) and made a column in one of my tables to represent an Enum from my C# classes.
The enum is
public enum ItemType
{
Build,
Stock,
Shell,
Parts,
[Display(Name="All Vehicles")]
AllTypesOfVehicles
}
I am trying to select certain records in an EF Linq Query by using this enum in the where clause. I simply cast the enum to its underlying int32 data type but it does not retrieve me the results I want.
var results = context.Items.Include(P => P.Manufacturer)
.Include(P => P.Category).Include(P => P.VehicleMake)
.Include(P => P.VehicleModel).Include(P => P.VehicleYear);
//Fetches specific type of item
if (TypeOfPart != StaticData.ItemType.AllTypesOfVehicles)
{
results.Where(P => P.Type == (int)TypeOfPart); //This does not work
}
else //fetches all vehicle types
{
results.Where(P => P.Type == 0 | P.Type == 1 | P.Type == 2);
}
Is this expected in EF? I know EF supports Enum from a code first approach but I don't see why this would cause a problem. I went into my Azure portal and wrote a manual query to see if I would get the results that I wanted and I did.
SELECT * FROM Items WHERE Type = 2
This yielded me only results that were of enum type "Shell". Even hardcoding the number 2 into the where clause in my EF query does not get me the results I want. I rechecked my code to make sure I wasn't overriding that where clause anywhere else and everything seems clean. Just to be sure I even called .ToList() right after the where clause but still got bad results.
I'm not quite sure what I'm missing here???
============Edit after first answer=======================
var results = context.Items.Include(P => P.Manufacturer)
.Include(P => P.Category).Include(P => P.VehicleMake)
.Include(P => P.VehicleModel).Include(P => P.VehicleYear);
//Fetches specific type of item
if (TypeOfPart != StaticData.ItemType.AllTypesOfVehicles)
{
var part = (int)TypeOfPart;
results.Where(P => P.Type == part);
List<Item> t = results.ToList();
}
else //fetches all vehicle types
{
results.Where(P => P.Type == 0 | P.Type == 1 | P.Type == 2);
}
You have to assign results.Where() back to results to get it work and try performing the cast outside EF query context:
//Fetches specific type of item
if (TypeOfPart != StaticData.ItemType.AllTypesOfVehicles)
{
var part = (int)TypeOfPart;
results = results.Where(P => P.Type == part ); //This does not work
}
else //fetches all vehicle types
{
results = results.Where(P => P.Type == 0 | P.Type == 1 | P.Type == 2);
}
And btw, should you just skip the P.Type related Where when you're trying to fetch all types of vehicles? It would mean you don't need else.
//Fetches specific type of item
if (TypeOfPart != StaticData.ItemType.AllTypesOfVehicles)
{
var part = (int)TypeOfPart;
results.Where(P => P.Type == part ); //This does not work
}

How to write this LINQ with foreach in a better way

I was doing project in MVC3 with Entity framework. I have a LINQ query with foreach. Everything is fine. But when the data size goes up, i was facing performance issues. I dont have much experience with LINQ. So I couldn't fix my issue. Pls have a look at my code and provide a better suggestion for me.
Code
List<int> RouteIds = db.Cap.Where(asd => asd.Type == 3).Select(asd => asd.UserId).ToList();
var UsersWithRoutingId = (from route in db.RoutingListMembers
where RouteIds.Contains(route.RoutingListId.Value) && route.User.UserDeptId == Id
select
new RoutingWithUser
{
UserId = route.UserId,
RoutingId = route.RoutingListId
});
var ListRouteValue = (from cap in db.CareAllocationPercents
where cap.Type == 3
select new UserWithDeptId
{
Year = (from amt in db.CareAllocations where amt.CareItemId == cap.CareItemId select amt.Year).FirstOrDefault(),
UserId = cap.UserId,
UserDeptId = (from userdept in db.Users where userdept.Id == cap.UserId select userdept.UserDeptId).FirstOrDefault(),
});
List<UserWithDeptId> NewRouteList = new List<UserWithDeptId>();
ListRouteValue = ListRouteValue.Where(asd => asd.Year == Year);
foreach (var listdept in ListRouteValue)
{
foreach (var users in UsersWithRoutingId)
{
if (users.RoutingId == listdept.UserId)
{
UserWithDeptId UserwithRouteObj = new UserWithDeptId();
UserwithRouteObj.UserId = users.UserId;
UserwithRouteObj.Year = listdept.Year;
UserwithRouteObj.UserDeptId = db.Users.Where(asd => asd.Id == users.UserId).Select(asd => asd.UserDeptId).FirstOrDefault();
NewRouteList.Add(UserwithRouteObj);
}
}
}
NewRouteList = NewRouteList.Where(asd => asd.UserDeptId == Id).ToList();
Thanks,
You have to use join in first statement. Examples of how to do this are for example here: Joins in LINQ to SQL
I have some idea for you:
First:
Take care to complete your where close into your linq query to get just what you need to.
With Linq on collection, you can remove one foreach loop. I don't know the finality but, i've tryied to write something for you:
var UsersWithRoutingId = (from route in db.RoutingListMembers
where RouteIds.Contains(route.RoutingListId.Value) && route.User.UserDeptId == Id
select
new RoutingWithUser
{
UserId = route.UserId,
RoutingId = route.RoutingListId
});
var ListRouteValue = (from cap in db.CareAllocationPercents
where cap.Type == 3
select new UserWithDeptId
{
Year = (from amt in db.CareAllocations
where amt.CareItemId == cap.CareItemId && amt.Year == Year
select amt.Year).FirstOrDefault(),
UserId = cap.UserId,
UserDeptId = (from userdept in db.Users
where userdept.Id == cap.UserId && userdept.UserDeptId == Id
select userdept.UserDeptId).FirstOrDefault(),
});
List<UserWithDeptId> NewRouteList = new List<UserWithDeptId>();
foreach (var listdept in ListRouteValue)
{
var user = UsersWithRoutingId.Where(uwri => uwri.RoutingId == listdept.UserId).FirstOrDefault();
if (user != null)
{
NewRouteList.Add(new UserWithDeptId { UserId=user.UserId, Year=listdept.Year, UserDeptId=listdept.UserDeptId });
}
}
return NewRouteList
Is that right for you ?
(i don't poll the db.user table do get the UserDeptId for the NewRouteList assuming that the one in the listdept is the good one)
Second:
Take care of entity data loading, if you have tables with foreign key, take care to remove the lazy loading if you don't need the children of your table to be loaded at same time. Imagine the gain for multiple table with foreign key pointing to others.
Edit:
Here is a link that explain it:
http://msdn.microsoft.com/en-us/library/vstudio/dd456846%28v=vs.100%29.aspx

Entity Framework code first - Many to Many - Include conditional

I have two Entities Store and Catalog, having many to many relationship using fluent Api. I want to get a Store by id with all the catalogs having status equals to "Published".
Below I try to write the following query but not getting the expected results.
var store = context.Stores.Include("Catalogs").Where(s => s.StoreID == id && s.Catalogs.Any(c => c.Status == "Published")).SingleOrDefault();
What you're asking for there is "give me the store with this ID, but only if it has a published catalog" (the "Any" call).
The easiest way to only get published catalogs would be to project them into an anonymous type:
var result = (from s in context.Stores
where s.StoreID == id
select new
{
Store = s,
Catalogs = s.Catalogs.Where(c => c.Status == "Published")
}).SingleOrDefault();
... or, in the fluent interface:
var result = context.Stores.Where(st => st.StoreID == id)
.Select(s => new
{
Store = s,
Catalogs = s.Catalogs.Where(c => c.Status == "Published"),
}).SingleOrDefault();
So result.Catalogs holds all the published catalogs that apply to result.Store.

Linq select subquery

As the title states, I'm trying to perform a select subquery in Linq-To-SQL. Here's my situation:
I have a database view which returns the following fields:
SourceId
LicenseId
LicenseName
CharacteristicId
CharacteristicName
Now I want to be able to store this in a model of mine which has the following properties
Id
Name
Characteristics (this is List which has Id, Name and Icon => Icon is byte[])
Here's the query I wrote which doesn't work:
var licensesWithCharacteristics =
_vwAllLicensesWithAttributesAndSourceIdRepository.GetAll()
.Where(x => x.SourceID == sourceId)
.Select(a => new LicenseWithCharacteristicsModel()
{
LicenseId = a.LicenseId,
LicenseName = a.LicenseName
,CharacteristicList = _vwAllLicensesWithAttributesAndSourceIdRepository.GetAll()
.Where(x => x.LicenseId == a.LicenseId)
.Select(c => new CharacteristicModel { Id = c.CharacteristicID, Name = c.CharacteristicName, Icon = c.Icon })
.Distinct().ToList()
})
.Distinct().ToList();
How would you solve this? I'm trying to do this in one query to keep my performance up, but I'm kind of stuck.
Your sample query and models are not that coherent (where does Icon come from, Characteristics or CharacteristicList), but anyway.
I do this in two parts, you can of course regroup this in one query.
I enumerate the result after the grouping, you may try to do without enumerating (all in linq to sql, but not sure it will work).
var groupedResult =
_vwAllLicensesWithAttributesAndSourceIdRepository.GetAll()
.Where(x => x.SourceID == sourceId)
.GroupBy(m => new {m.LicenseId, m.LicenseName})
.ToList();
var results = groupedResult.Select(group => new LicenseWithCharacteristicsModel {
LicenseId = group.Key.LicenseId,
LicenseName = group.Key.LicenseName,
Characteristics = group.Select(m=> new CharacteristicModel {
Id = m.CharacteristicId,
Name = m.CharacteristicName
}).ToList()
});
in "single query"
_vwAllLicensesWithAttributesAndSourceIdRepository.GetAll()
.Where(x => x.SourceID == sourceId)
.GroupBy(m => new {m.LicenseId, m.LicenseName})
.Select(group =>
new LicenseWithCharacteristicsModel
{
LicenseId = group.Key.LicenseId,
LicenseName = group.Key.LicenseName,
Characteristics = group.Select(m =>
new CharacteristicModel
{
Id = m.CharacteristicId,
Name = m.CharacteristicName
}).ToList()
});

Resources