c# - Is there a way to access a private property in a where clause? -
i'm trying directly map domain model ef. end introduced private property in model so:
private icollection<tag> tagsinternal { get; set; } public article(guid id, ... , ienumerable<tag> tags) : base(id) { ... this.tagsinternal = new list<tag>(tags.where(i => != null)); } public ienumerable<tag> tags { { return this.tagsinternal.asenumerable(); } }
in order access ef 'backing property' added handful of extension methods:
public static class fluentapiextensions { public static manynavigationpropertyconfiguration<tentitytype, ttargetentitytype> hasmany<tentitytype, ttargetentitytype>(this entitytypeconfiguration<tentitytype> mapper, string propertyname) tentitytype : class ttargetentitytype : class { var lambda = getlambdaexpression<tentitytype>(propertyname); return mapper .hasmany((expression<func<tentitytype, icollection<ttargetentitytype>>>)lambda); } public static manytomanynavigationpropertyconfiguration<tentitytype, ttargetentitytype> withmany<tentitytype, ttargetentitytype>(this manynavigationpropertyconfiguration<tentitytype, ttargetentitytype> mapper, string fieldname) tentitytype : class ttargetentitytype : class { var lambda = getlambdaexpression<ttargetentitytype>(fieldname); return mapper .withmany((expression<func<ttargetentitytype, icollection<tentitytype>>>)lambda); } private static lambdaexpression getlambdaexpression<t>(string propertyname) { var type = typeof (t); var parameterexpression = expression.parameter(type, "type"); var expression = (expression)parameterexpression; var propertyinfo = type .getproperty(propertyname, bindingflags.public | bindingflags.nonpublic | bindingflags.instance); if (propertyinfo == null) throw new argumentexception(string.format("there no property named '{0}' on type '{1}'.", propertyname, type.name)); var propertyexpression = expression.property(expression, propertyinfo); return expression.lambda(propertyexpression, parameterexpression); } }
i in position pick navigation properties this:
public maybe<article> getarticle(guid articleid) { articleid.mustnotbenull(); var article = this.unitofwork.context.articles .include("tagsinternal") .firstordefault(a => a.id == articleid); return article == null ? new maybe<article>() : new maybe<article>(article); }
however, whole thing breaks down when trying execute query has "tags" in clause, example
var test = this.unitofwork.context.articles .where(a => a.tags.count() > 0);
the message is
the specified type member 'tags' not supported in linq entities. initializers, entity members, , entity navigation properties supported.
is there way remedy situation? i'm considering keep ef out of model , map instead or maybe go down state object route suggested vaughn vernon.
you said you're mapping domain model ef. in mind you'll want keep ef classes simple possible. exist persist domain model. means:
- do not put methods on ef classes.
- do not use other default constructor.
- only use public methods.
- map domain classes ef classes manually or use automapper.
also, based on code above looks have own unitofwork implementation. unnecessary dbcontext
is unit of work. (use di container manage dbcontext
sessions. want them have per-request lifetime if web application.)
i'm not sure why you're returning maybe<article>
above. if it's not found, return null. in controller, if getarticle()
returns null
, return httpnotfound()
controller.
if above, should clear confusion , remove lot of mapping code have above.
Comments
Post a Comment