c# - Why does EntityFramework 6 not support explicitly filtering by Discriminator? -
the following small ef6 program demonstrate issue.
public abstract class base { public int id { get; set; } public abstract int typeid { get; } } public class suba : base { public override int typeid => 1; } public class subaa : suba { public override int typeid => 2; } public class subb : base { public override int typeid => 3; } public class subc : base { public override int typeid => 4; } public class devartcontext : dbcontext { public virtual dbset<base> bases { get; set; } public devartcontext() { } protected override void onmodelcreating(dbmodelbuilder modelbuilder) { base.onmodelcreating(modelbuilder); modelbuilder.entity<base>() .map<suba>(x => x.requires(nameof(suba.typeid)).hasvalue(1)) .map<subaa>(x => x.requires(nameof(subaa.typeid)).hasvalue(2)) .map<subb>(x => x.requires(nameof(subb.typeid)).hasvalue(3)) .map<subc>(x => x.requires(nameof(subc.typeid)).hasvalue(4)); } } public class program { public static void main(string[] args) { using (devartcontext ctx = new devartcontext()) { // prevent model-changes wrecking test ctx.database.delete(); ctx.database.create(); var result = ctx.bases.where(x => x.typeid == 1); // throws on materialization, why? foreach (var entry in result) { console.writeline(entry); } } console.readline(); } }
the jist of this: have tph-model explicitly configured discriminator (typeid
in case). try query specific subtype using typeid because using is
operator in our hypothetical example return subaas, not subas.
i modify above where(x => x suba && !(x subaa))
going break add subab, , automating building exact-filter-linq-to-entities-helper-method slow because method has decent amount of reflection. not mention generated sql of above horrendous because ef/my sql provider not optimize properly.
now trying above results in notsupportedexception
being thrown when query gets materialized, states because typeid
not member of entity, cannot use filtering.
i went around ways circumvent this, best thing find snippet automatically generating where(x => x suba && !(x subaa))
version solve problem, have around this.
so question is: why entityframework not support this?
this soultion working excatly wish donot change ^^ "never change running system" :)
you can use enum instead of integers, give code more type safety!
static void main(string[] args) { using (devartcontext ctx = new devartcontext()) { // prevent model-changes wrecking test ctx.database.delete(); ctx.database.create(); ctx.bases.add(new suba()); ctx.bases.add(new subaa()); ctx.bases.add(new subb()); ctx.savechanges(); var result = ctx.bases.where(x => x.typeid == 1); // throws on materialization, why? foreach (var entry in result) { console.writeline(entry); } } console.readline(); } public abstract class base { public int id { get; set; } public virtual int typeid { get; protected set; } } public class suba : base { public override int typeid { get;protected set; } = 1; } public class subaa : suba { public override int typeid { get; protected set; } = 2; } public class subb : base { public override int typeid { get; protected set; } = 3; } public class subc : base { public override int typeid { get; protected set; } = 4; } public class devartcontext : dbcontext { public dbset<base> bases { get; set; } public devartcontext() { } }
result in db:
id typeid discriminator 1 1 suba 2 2 subaa 3 3 subb
Comments
Post a Comment