EF 4.0 : Include based on condition - entity-framework-4

I have the following Linq Expession being used in EF 4
var map = model.CDM_SubsidiaryDocumentMap.Where(m => m.SubsidiaryID == subsidiaryID)
.Include("CDM_DocumentType")
.Include("CDM_DocumentType.CDM_DocumentHeader")
**(Need Help here) Filter based on CDMDocumentType.CDM_DocumentHeader.ContactID == 123**
.OrderBy(m => m.UISortOrder)
.ToList();
How do I write the missing statement above, where in I include the nested child based on contactID filter. Also note that CDM_DocumentType.CDM_DocumentHeader is a collection. Much appreciated

If you don't mind using the from syntax. Try something like this:
var map = (from m in model.CDM_SubsidiaryDocumentMap
from dmh in m.CDM_DocumentType.CDM_DocumentHeader
where m.SubsidiaryID == subsidiaryID
&& dmh.ContactID == 123
order by m => m.UISortOrder
select m).ToList();
If that doesn't work show more of your Entity Model, as I made and assumtion that CDM_DocumentType is a navigation property on CDM_SubsidiaryDocumentMap.

Related

LINQ to SQL - Filtering the dataset between two nested collections

I have an MVC 3 project in Visual Studio c#. I have a LINQ to SQL query which works fine and by following an example listed elsewhere on stackoverflow:
Comparing two lists using linq to sql
I have been able to successfully reduce my results where my two nested collections match. This is the bit of code that did the trick (example from the link above):
var anyDesiredSkills = canidateSkills.Any( c => desiredSkills.Select( ds => ds.SkillId ).Contains( c.SkillId ) );
I've adapted this successfully, but now I need to be able to filter records using more than one condition. I was wondering if anyone would be able to adapt the above to show how you could include more than one condition?
To give you some background on what my goal is:
A search page where you can select any number of contacts
Each contact added to the search criteria may/may not have a 'role' assigned. If a role is present this should be factored in to the query.
Results returned based on this dynamic criteria.
Thanks in advance for any and all help :O)
It sounds like you're looking for something like:
var desiredSkillIds = desiredSkills.Select(_=>_.SkillId).ToList();
var matchingContacts =
from contact in Contacts
where contact.Role == null || desiredRoles.Contains(contact.Role)
where contact.Skills.Any(cs=> desiredSkillIds.Contains(cs.SkillId))
select contact;
Or in method-based syntax:
var matchingContacts = Contacts
.Where(contact => contact.Role == null || desiredRoles.Contains(contactRole))
.Where(contact => contact.Skills.Any(cs => desiredSkillIds.Contains(cs.SkillId)));
Here's the final code I used:
servicelist = servicelist.Where(
d => d.ContactSelection.Any(
h => model.ContactFilter.Select(ds => ds.StaffNumber).Contains(h.StaffNumber)
&&
model.ContactFilter.Select(ds => ds.ContactRole).Contains(h.ContactRole) || model.ContactFilter.Select(ds => ds.StaffNumber).Contains(h.StaffNumber) && model.ContactFilter.Select(ds => ds.ContactRole).Contains("0"))
);
Note that the last filter .Contains("0) is the value of '-- select role --' which is an option injected in to the drop down. Hope this helps anyone else!

Problem creating an Entity object/queryable from the result of a LINQ join in MVC

I'm attempting to write a search function for a database table that needs to access information from related tables using Entity Framework. However, I'm running into problems getting the data back out of my initial query after doing a join on the parent table and the related tables. My code currently looks like this. I initialize my queryable object
IQueryable<PurchaseOrder> po = _context.PurchaseOrders;
Where PurchaseOrder is an Entity type. Then there is a series of blocks like this.
if (!String.IsNullOrEmpty(searchViewModel.Comment)){
var helper = _context.PurchaseOrderComments.Where(x => x.CommentText.Contains(searchViewModel.Comment));
var mid = po.Join(helper, r => r.PurchaseOrderID, u => u.PurchaseOrderID, (r, u) =>
new
{
PurchaseOrderID = r.PurchaseOrderID,
PurchaseOrderNumber = r.PurchaseOrderNumber,
VendorID = r.VendorID,
ContractNumber = r.ContractNumber,
BuyerUserID = r.BuyerUserID
});
po = mid.Select(x => new PurchaseOrder
{
PurchaseOrderID = x.PurchaseOrderID,
PurchaseOrderNumber = x.PurchaseOrderNumber,
VendorID = x.VendorID,
ContractNumber = x.ContractNumber,
BuyerUserID = x.BuyerUserID
});
}
After each block, po is passed to the next search parameter. However, as you might guess, my program complains that I can't build a complex type in mid's Select statement. I've also tried building PurchaseOrder objects from the contents of mid, inserting them into a new List of PurchaseOrders, and converting that list into a queryable to assign to po to pass on to the next block. However, that changes po's data type from System.Data.Object.ObjectSet to System.Collections.Generic.List, which then throws an InvalidOperationException the next time I try and iterate through it using a foreach.
So my question is, are there any obvious mistakes in my approach or any suggestions for other ways to approach the problem? Thanks very much for any help.
I think you're making this more complicated than it needs to be. If I understand what you're trying to do, you should be able to do something like this:
if (!String.IsNullOrEmpty(searchViewModel.Comment)){
po = po.Where(
o => o.PurchaseOrderComments.Any(
c => c.CommentText.Contains(searchViewModel.Comment)));
}
StriplingWarrior's solution is the best way. In case that your PurchaseOrder class really doesn't have a navigation collection of PurchaseOrderComments (which would force you to use a join) the following should work and is simpler as your double projection:
po=po.Join(helper, r => r.PurchaseOrderID, u => u.PurchaseOrderID, (r, u) => r);

NHibernate QueryOver: How to join unrelated entities?

I have the following query working which gets the results I want:
int associatedId = 123;
MyObject alias = null;
var subQuery = QueryOver.Of<DatabaseView>()
.Where(view => view.AssociatedId == associatedId)
.And(view => view.ObjectId == alias.ObjectId)
.Select(view => view.ObjectId);
var results = session.QueryOver<MyObject>(() => alias)
.WithSubquery.WhereExists(subQuery)
.List();
The DatabaseView has been mapped as an actual NHibernate entity (so I can use it with QueryOver), but it is not associated to MyObject in the HBM mappings.
This query returns an IList<MyObject> using a SELECT ... FROM MyObject WHERE EXISTS (subquery for DatabaseView here). How can I re-write this to return the same data but using a JOIN instead of sub query?
In NHibernate 5.1+ it's possible for QueryOver/Criteria via Entity Join:
int associatedId = 123;
MyObject alias = null;
DatabaseView viewAlias = null;
var results = session.QueryOver<MyObject>(() => alias)
.JoinEntityAlias(() => viewAlias, () => viewAlias.ObjectId == alias.ObjectId && viewAlias.AssociatedId == associatedId)
.List();
Criteria example:
int associatedId = 123;
var results = session.CreateCriteria<MyObject>("alias")
.CreateEntityAlias(
"viewAlias",
Restrictions.EqProperty("viewAlias.ObjectId", "alias.ObjectId")
&& Restrictions.Eq("viewAlias.AssociationId", associatedId),
JoinType.InnerJoin,
typeof(DatabaseView).FullName)
.List();
You can join onto unrelated entities with Linq in NHibernate 3+
Funnily enough you use the join query expression element:
from type1 in Repository.Query<MyType1>()
join type2 in Repository.Query<MyType2>()
on type1.Id equals type2.Id
Note: Repository.Query is just returning an IQueryable Query from the session
I'm hoping there is a solution for QueryOver as I don't always want to model two-way relationships in my domain but they are still useful for querying.
Also, you can map a Access="noop" 2 way relationship using Criteria API without putting into your POCO classes:
http://ayende.com/blog/4054/nhibernate-query-only-properties
I realize this question is 5 years old, and the "correct" answer is definitely that you can't do this with QueryOver, as the other answers indicate. However, if you really need this functionality (as I did), there is a decent workaround that I found.
The solution is to use a "loader query" with native SQL in your mapping XML to produce a related collection (see http://nhibernate.info/doc/nhibernate-reference/querysql.html#querysql-load). In the OP's specific example, you would go ahead and map your DatabaseView as an entity as suggested, and then write the following in your mapping:
<class name="MyObject"...>
...
<set name="MyViews" inverse="true">
<key column="ObjectId" foreign-key="none"/>
<one-to-many class="MyObject"/>
<loader query-ref="myObjectViewsLoadQuery"/>
</set>
</class>
Then we just need to define our named myObjectViewsLoadQuery in raw SQL to explain to NH how to join the two:
<sql-query name="myObjectViewsLoadQuery">
<load-collection alias="view" role="MyObject.MyViews"/>
SELECT view.*
FROM DatabaseView view
WHERE view.ObjectId = :id
</sql-query>
We can now pretend like there is a "real" collection named MyViews relating MyObject to DatabaseView in our query:
MyObject alias = null;
DatabaseView view = null;
var results = session.QueryOver<MyObject>(() => alias)
.JoinAlias( () => alias.MyViews, () => view )
//.Where( () => view.Property == "myValue" ) // optionally, restrict the view etc.
.List();
Certainly, this is a lot of trouble to go through if you only care about an "elegant" query. However, if the reason you are using QueryOver is that you want to be able to accept arbitrary input Expressions to filter your DatabaseView by, or various similar activities, this works very nicely.

Entity Framework 4 Linq help - Pulling data from multiple tables filtered

Not sure how this is done, I have my .edmx set up so that the navigation properties match the foreign key relationships on the tables. Not sure if I still need to perform joins or if EF will give me access to the related table data through the navigational properties automatically.
What I need to do it get all the ContentSections and their associated ContentItems based on the ContentView and filtered by the DiversionProgram.CrimeNumber.
I would like to get back IEnumerable, for each ContentSection it should have access to it's ContentItems via the navigation property ContentItems
Thanks
Something like:
using(Entities context = new Entities())
{
IEnumerable<ContentSection> enumerator = context.ContentSections
.Include("ContentItems")
.Where<ContentSection>(cs => cs.ContentView.ContentViewID == someID && cs.ContentItems.Where<ContentItem>(ci => ci.DiversionProgram.CrimeNumber == someCrimeNumber))
.AsEnumerable<ContentSection>
}
I've interpreted
based on the ContentView
as cs.ContentView.ContentViewID == someID
This will give you all the ContentSections for a given ContentView. And interpreted
filtered by the DiversionProgram.CrimeNumber
as cs.ContentItems.Where<ContentItem>(ci => ci.DiversionProgram.CrimeNumber == someCrimeNumber)
which will give you all those ContentItems that have a specific CrimeNumber.
Or did you mean something else with based on / filtered by. Maybe OrderBy, or all those ContentSections where Any of it's ContentItems would have a certain CrimeNumber?
You can eager load to get all associated records, but when you want to start filtering/ordering, don't bother with Include.
Just do a projection with anonymous types and EF will work out what it needs to do. It's a bit hairy, but it'll work. If it get's too complicated, bite the bullet and use a SPROC.
Now, with that caveat, something like this (off the top of my head):
var query = ctx.ContentView
.Select(x => new
{
ContentSections = x.ContentSections
.Where(y => y.ContentItems
.Any(z => z.DivisionProgram.CrimeNumber = 87))
}).ToList().Select(x => x.ContentSections);
If you use the CTP5 you can do something very unique it looks like this:
var context = new YourEntitiesContext();
var query = context.ContentView.Include(cs => cs.ContentSections
.Select(ci => ci.ContentItems
.Select(dp => dp.DiversionProgram)
.Where(dp.CrimeNumber == crimeNumber)))
.Where(cv => cv.ContentViewID == contentViewID).FirtsOrDefault();
You can learn more about the CTP5 and how it can be used in Database first scenario here
var query = from t1 in studentManagementEntities.StudentRegistrations
join t2 in studentManagementEntities.StudentMarks
on t1.StudentID equals t2.StudentID
select new
{
t1.selected column name,
t2.selected column name
};

ADO.Net Entity Framework/Linq

I'm look at learning a bit more ASP.Net MVC and Linq To Entity.
I'm working on a project using this and am having a problem with the following line of code
ViewData["ProjectName"] = db.Projects.FirstOrDefault(p => p.ProjectId == task.ProjectId).ProjectName;
It works fine when the record exists but if no record exist it errors because I am trying to examine the ProjectName property of a null object. I realise I could cast the object to a variable and test if its null before storing the ProjectName into the ViewData but am just wondering if there is a neater way of doing this?
I know its a simple question and I could just work around it but if there is a better way of doing this it would be good to know.
Thanks
Gavin
var project = db.Projects.FirstOrDefault(p => p.ProjectId == task.ProjectId);
if (project != null)
{
ViewData["ProjectName"] = project.ProjectName;
}
else
{
//........
}
No cast needed.
Or skip the condition altogether and do this:
ViewData["ProjectName"] = db.Projects.Where(p => p.ProjectId == task.ProjectId)
.Select(p => p.ProjectName).FirstOrDefault();

Resources