c# - Adding condition to mapping for child collection in Entity Framework 6 similar to NHibernate's "where" -
in nhibernate, there where
mapping allows specify condition on property mapping affects how pulled database. example, if wanted implement soft delete , exclude deleted items set, map so:
fluentnhibernate
// in class parentmap : classmap hasmany(x => x.children).where("isdeleted = 0");
hbm.xml
<class name="parent" table="[parents]"> <bag cascade="all" lazy="true" name="children" where="isdeleted = 0"> <!-- rest of map here --> </bag> </class>
is there similar in entity framework 6?
the closest thing found library called entityframework.filters, allows add global filters properties, doesn't seem work when property collection.
to give better example of why mapping necessary, let's have class has collection of objects have recursive child entity relationship (i.e., collection of objects of same type). follow basic structure:
public class reportoutline { public long id { get; set; } public string title { get; set; } public string author { get; set; } public virtual icollection<outlineitem> outlineitems { get; set; } } public class outlineitem { public long id { get; set; } public string name { get; set; } public long reportoutlineid { get; set; } public long? parentoutlineitemid { get; set; } public virtual reportoutline reportoutline { get; set; } public virtual outlineitem parentoutlineitem { get; set; } public virtual icollection<outlineitem> outlineitems { get; set; } }
and these mapped ef fluent api this:
modelbuilder.entity<reportoutline>() .haskey(o => o.id) .hasmany(o => o.outlineitems) .withrequired(i => i.reportoutline) .hasforeignkey(i => i.outlineid); modelbuilder.entity<outlineitem>() .haskey(p => p.id) .hasmany(p => p.outlineitems) .withoptional(c => c.parentoutlineitem) .hasforeignkey(c => c.parentoutlineitemid);
this produces correct database structure, , records fine. here's example of outlineitems
table 2 items on reportoutline
, if 1 had 2 child items (four altogether):
id name reportoutlineid parentoutlineitemid 1 introduction 1 null 2 pets 1 null 3 cats 1 2 4 dogs 1 2
when reportoutline
gets loaded through dbcontext
, however, since reportoutlineid
matched outline's id
, reportoutline.outlineitems
getting populated 4 items. results in sub-items appearing both under parent items , main outline itself:
title: report author: valverij i. introduction (id: 1) ii. pets (id: 2) a. cats (id: 3) b. dogs (id: 4) iii. cats (id: 3) <--- duplicated iv. dogs (id: 4) <--- duplicated
now, if using nhibernate fluentnhibernate, specify where
condition on entity mapping, reportoutline.outlineitems
only pulls parent items:
// in reportoutlinemap hasmany(x => x.outlineitems).where("parentoutlineitemid null");
without that, have remember only access reportoutline
objects through pre-written query explicitly deals outlineitem
collection.
you add "rootoutlineitems" property reportoutline class filters you, call when want 1st level:
public class reportoutline { public long id { get; set; } public string title { get; set; } public string author { get; set; } public virtual icollection<outlineitem> outlineitems { get; set; } public icollection<outlineitem> rootoutlineitems { { return outlineitems.where(p=> p.parentoutlineitem == null); } } }
another option make outlineitem's reportoutline nullable, , ever set either reportoutline or parentoutlineitem property, that's little iffy, plus you'd have navigate tree if ever want all items.
Comments
Post a Comment