3

공통 속성을 가진 두 개의 엔터티가 있습니다. 공통 속성을 사용하여 쿼리의 일부를 적용해야합니다. 문제는이 방법을 사용엔터티 프레임 워크 공용 위치

public interface IContract 
{ 
    string Name{get;set;} 
} 

public class Entity1 : IContract 
{ 
    public string Name{get;set;} 
} 

public class Entity2 : IContract 
{ 
    public string Name{get;set;} 
} 

public class Repository 
{ 
    public IQueryable<T> Filter<T>(IQueryable<T> query, Request request) where T : IContract 
    { 
     return query.Where(x => x.Name== request.Name); 
    } 
    public IQueryable<Entity1> GetEntitity1() 
    { 
     return Filter(entities.Entity1, new Request { Name = "X" }; 
    } 

    public IQueryable<Entity2> GetEntitity2() 
    { 
     return Filter(entities.Entity2, new Request { Name = "X" }; 
    } 
} 

이후 .ToList() 내가받을 적용 : 그래서 나는이 작업을 수행하기로 결정 NotSupportedException이 있습니다. LINQ to Entities는 EDM 프리미티브 또는 열거 형을 캐스팅하는 기능 만 지원합니다.

나는 그것을 고칠 방법이 있거나 ObjectQuery의 Where (문자열)을 사용해야합니까?

감사

답변

0

문제는 T에 대한 타입 제약의 인터페이스입니다이다. 필터 메소드의 결과는 기본적으로 이와 같은 쿼리입니다.

entities.Entity1.Where(p => ((IContract)p).Name == request.Name); 

이 ((IContract) p) 캐스트는 SQL 문으로 변환 할 수 없습니다. 이 캐스트는 귀하의 경우에는 쓸모가 없으므로 간단히 쿼리 식에서 제거 할 수 있습니다. 이를 수행하는 가장 좋은 방법은 ExpressionVisitor입니다.

public IQueryable<T> Filter<T>(IQueryable<T> query, Request request) where T : IContract 
{ 
    var result = query.Where(x => x.Name == request.Name); 
    result = RemoveContract<T, IContract>(result); 
    return result; 
} 

public IQueryable<T> RemoveContract<T, TContract>(IQueryable<T> query) where T : TContract 
{ 
    var exp = query.Expression; 
    exp = new RemoveConvertExpressionVisitor<TContract>().Visit(exp); 
    return query.Provider.CreateQuery<T>(exp); 
} 

private class RemoveConvertExpressionVisitor<TContract> : ExpressionVisitor{ 
    public override Expression Visit(Expression node) 
    { 
     var unary = node as UnaryExpression; 
     if (unary != null && unary.Type == typeof(TContract)) { 
      return unary.Operand; 
     } 
     return base.Visit(node); 
    } 
} 

RemoveContract 메서드를 호출하면 쿼리가 다음과 같이 표시됩니다.

entities.Entity1.Where(p => p.Name == request.Name);