c# - Linq to SQL Domain Entity Property Comparison Using Expressions -
i trying create linq sql expressions generically allow same properties compared on 2 different domain entity records. general idea define properties on entities need compared, compare each of these properties 1 one check equality/inequality. identifying properties need compared creating expressions on domain entities:
public class compareentityproperty<tentity> tentity : ientity { public expression<func<tentity, object>> entitypropertyexpression { get; set; } public expression<func<tentity, tentity, bool>> compare { { var expression = entitypropertyexpression; return (entitya, entityb) => object.equals(expression.invoke(entitya), expression.invoke(entityb)); } } }
then set generic entity, set such:
public class foo : ientity { public long? bar { get; set; } }
i set using:
public class foocompare { public ienumerable<compareentityproperty<foo>> comparelist { { return new [] { new compareentityproperty<foo>() { entitypropertyexpression = entity => entity.bar } }; } } }
the problem i'm seeing appears related how property expression set using 'object' type of property. when expression compiled, attempts convert property type (in case nullable long object, sql not know how , error like:
unable cast type 'system.nullable`1[[system.int64, mscorlib, version=4.0.0.0, culture=neutral, publickeytoken=b77a5c561934e089]]' type 'system.object'.
this appears confirmed when add watch , @ expression that's generated:
entity => convert(entity.bar)
it looks attempting first convert property value type 'object' type can work with, hence error.
first, correct in assumption error? there way around this? there way set property expression dynamic rather typed 'object'? or there option skirting issue?
thanks!
edit: using linqkit library, provides logic necessary handle 'invoke' method call on expression translated sql.
i'm not sure library you're using make current code work you, if want generate expressions hand you're going need to:
grab
body
entitypropertyexpressionentity.bar
create new parameterexpression represent second lambda parameter.
use expression tree visitor create new expression replaces instances of lambda parameter instances of new parameter
entity2.bar
use
expression.call()
generate method callequals
method, passing in 2 member expressionsobject.equals(entity.bar, entity2.bar)
use
expression.andalso()
combine number of these expression trees together:object.equals(entity.foo, entity2.foo) && object.equals(entity.bar, entity2.bar) && object.equals(entity.baz, entity2.baz)
use
expression.lambda<>()
generate new lambda expression takes 2 parameters , applies them expression you've built:(entity, entity2) => object.equals(entity.foo, entity2.foo) && object.equals(entity.bar, entity2.bar) && object.equals(entity.baz, entity2.baz)
if entity framework or linq sql having issues concept of translating values object
s pass object.equals()
, you'll need use reflection in step 4 above find appropriate .equals()
instance method , call instead.
Comments
Post a Comment