28991

Expression generated based on interface

I'm geting the exception <strong>Unable to cast the type 'MySomeTypeThatImplementsISomeInterfaceAndIsPassedAs[T]ToTheClass' to type 'ISomeInterface'. LINQ to Entities only supports casting Entity Data Model primitive types.</strong>

my repository looks like

public interface IRepository<T> { IQueryable<T> Get(System.Linq.Expressions.Expression<System.Func<T, bool>> Query); }

Also, I have the service class

public abstract class FinanceServiceBase<TAccount, TParcel, TPayment> where TAccount : IAccount where TParcel : IParcel where TPayment : IPayment { //... IRepository<TPayment> ParcelRepository {get; private set;} public bool MakePayment(TPayment payment) { //... ParcelRepository.Get(p => p.ParcelId == 2); // here my exception is thrown // **p.ParcelId is in IParcel** //... } } //...

With this class I can control many things about finances without rewrite code for other programs. I've did the class with 3 generic parameters because I couldn't use IRepository because my repository can't be <out T>

<strong>ParcelId is Int32</strong> TParcel is typeof(ParcelToReceive) that is an entity who implement IParcel, and was generated with codeonly

The problem occurs when I call Get and the resultant lambda looks like

(**(ISomeInterface)**$p).SomeInterfaceMember ==

instead of

($p.SomeInterfaceMember)

so, entity framework try do the cast and throws the exception. What I want to know is: is there anyway to tell linq that the lambda field p.ParcelId is from <strong>TParcel</strong> and not from <strong>IParcel</strong>.

Already tried (with no luck):

p => ((TParcel)p).ParcelId

Thanks

Answer1:

It seems that setting the generic constraints from where TAccount : IAccount to something like where TAccount : class, IAccount tells entity framework that the expression contains a <strong>class</strong> and it will not make the explicit cast that it would do for primitive EDM and enum types.

Answer2:

I’m afraid you can’t do this because fundamentally you are accessing the property that is declared in the interface. LINQ-to-Entities doesn’t seem to support that; you need to call the property in the real entity type.

One way you could solve this is by passing the parcelId property as an expression tree in a parameter, and then construct a lambda expression dynamically at runtime using the property in that parameter:

public bool MakePayment(TPayment payment, Expression<Func<TParcel, int>> parcelIdExpr) { // You can use any expression involving parcelId here Expression<Func<int, bool>> expr = parcelId => parcelId == 2; // This is the parameter of the new lambda we’re creating var parameter = Expression.Parameter(typeof(TParcel)); // This constructs the lambda expression “p => expr(p.ParcelId)”, // where “expr” is the lambda expression declared above var lambda = Expression.Lambda(Expression.Invoke(expr, Expression.Invoke(parcelIdExpr, parameter)), parameter); ParcelRepository.Get((Expression<Func<TParcel, bool>>) lambda); } [...] myFinanceService.MakePayment(myPayment, p => p.ParcelId);

If you don’t want to have to pass this extra parameter every time you call MakePayment, then you could in theory retrieve the property by name with a string literal; however, this is unsafe because it doesn’t ensure that it’s the right property which implements the interface. Also, this is a very roundabout way of doing it, so no guarantees:

public bool MakePayment(TPayment payment) { Expression<Func<int, bool>> expr = parcelId => parcelId == 2; var parameter = Expression.Parameter(typeof(TParcel)); // This is the expression “p.ParcelId”, where “p” is the parameter var propertyExpression = Expression.Property(parameter, "ParcelId"); var lambda = Expression.Lambda(Expression.Invoke(expr, propertyExpression), parameter); ParcelRepository.Get((Expression<Func<TParcel, bool>>) lambda); }

You can factor this out into a generic utility method:

public static class Utils { public static Expression<Func<TParameter, TResult>> CombineLambdas<TParameter, T, TResult>( Expression<Func<TParameter, T>> lambda1, Expression<Func<T, TResult>> lambda2 ) { var parameter = Expression.Parameter(typeof(TParameter)); var lambda = Expression.Lambda(Expression.Invoke(lambda2, Expression.Invoke(lambda1, parameter)), parameter); return (Expression<Func<TParameter, TResult>>) lambda; } } public bool MakePayment(TPayment payment, Expression<Func<TParcel, int>> parcelIdExpr) { ParcelRepository.Get(Utils.CombineLambdas( parcelIdExpr, parcelId => parcelId == 2)); }

Recommend

  • php paypal Server-side REST integration failure
  • Angular handle for 500 server errors
  • Order of join conditions important?
  • (MasterCard Virtual Payment Client) migs integration php
  • Alamofire HTTP requests fails
  • how to activate digital goods on paypal Mexico
  • Proven correct receipt module
  • How to add payment integration with Google Docs Add-ons?
  • woocommerce payment methods
  • Expression generated based on interface
  • Is it possible to transfer money from PayPal account to a bank account or credit card?
  • Active link turn different color
  • Paypal REST api - How to control the display language?
  • trigger event after specific time
  • C# - Get value from a specific tag in XML document
  • Paypal Parallel Payment with Multiple Currencies
  • App crashing when buying in-app purchase
  • Relationship between orders, customers and products?
  • is paypal's iphone sdk for payment approved by apple? [closed]
  • Why Is jQuery Not Submitting This Form? (Or What Have I Done Wrong? :-p)
  • Send money from Braintree
  • Visual Studio not stopping on an exception being thrown
  • Eloquent Relationship on Partial Match
  • How do I add a File Type Association in a Windows Phone 8.1 app manifest?
  • Issue with routerLink directive
  • Redirect to Post Method/Action
  • output of program is not same as passed argument
  • Javascript + PHP Encryption with pidCrypt
  • Adding custom controls to a full screen movie
  • Cannot Parse HTML Data Using Android / JSOUP
  • How to set the response of a form post action to a iframe source?
  • JTable with a ScrollPane misbehaving
  • Getting Messege Twice Using IMvxMessenger
  • Change div Background jquery
  • Qt: Run a script BEFORE make
  • unknown Exception android
  • reshape alternating columns in less time and using less memory
  • How can i traverse a binary tree from right to left in java?
  • failed to connect to specific WiFi in android programmatically
  • How can I use threading to 'tick' a timer to be accessed by other threads?