2011-05-02 95 views
1

我有這個問題,我真的不知道如何解決它。在提出這個問題之前,我問了兩個問題,但沒有得到我的情況的正確答案。這是詳細的問題。 我有一個接口,默認的實現:將一個方法轉換爲實體表達式以查詢實體框架

public interface IEntityPriceDefinition 
{ 
    PriceDefinition PriceDefinition { get; } 

    bool IsMatch(long additionId); 

    bool IsMatch(long? entityId, long? inviterId, long? routeId, long? luggageTypeId); 

    bool IsMatch(long? entityId, long? inviterId, long? routeId, long? luggageTypeId, 
     long additionId); 

    bool IsMatch(long? entityId, Task3 task); 

    bool IsMatch(long? entityId, Task3 task, long additionId); 
} 

public class EntityPriceDefinition : IEntityPriceDefinition 
    { 
     private PriceDefinition _PriceDefinition; 
     private Func<long?, bool> _IsEntityIdMatch; 
     private Func<Task3, long?> _TaskValue; 

     public PriceDefinition PriceDefinition { get { return _PriceDefinition; } } 

     internal EntityPriceDefinition(
      PriceDefinition priceDefinition, 
      Func<long?, bool> isEntityIdMatch, 
      Func<Task3, long?> taskValue) 
     { 
      _PriceDefinition = priceDefinition; 
      _IsEntityIdMatch = isEntityIdMatch; 
      _TaskValue = taskValue; 
     } 

     public bool IsMatch(long additionId) 
     { 
      return PriceDefinition.AdditionsPrices.Any(x => x.AdditionId == additionId); 
     } 

     private bool IsMatch(long? inviterId, long? routeId, long? luggageTypeId) 
     { 
      bool isMatch = inviterId.HasValue || routeId.HasValue || luggageTypeId.HasValue; 
      if (isMatch) 
      { 
       if (PriceDefinition.InviterId.HasValue && inviterId.HasValue) 
       { 
        if (PriceDefinition.InviterId.Value != inviterId.Value) { isMatch = false; } 
       } 
       if (PriceDefinition.LuggageTypeId.HasValue && luggageTypeId.HasValue) 
       { 
        if (PriceDefinition.LuggageTypeId.Value != luggageTypeId.Value) { isMatch = false; } 
       } 
       if (PriceDefinition.RouteId.HasValue && routeId.HasValue) 
       { 
        if (PriceDefinition.RouteId.Value != routeId.Value) { isMatch = false; } 
       } 
      } 
      return isMatch; 
     } 

     public bool IsMatch(long? entityId, long? inviterId, long? routeId, long? luggageTypeId) 
     { 
      return _IsEntityIdMatch(entityId) && IsMatch(inviterId, routeId, luggageTypeId); 
     } 

     public bool IsMatch(long? entityId, long? inviterId, long? routeId, long? luggageTypeId, 
      long additionId) 
     { 
      return IsMatch(entityId, inviterId, routeId, luggageTypeId) && IsMatch(additionId); 
     } 

     public bool IsMatch(long? entityId, Task3 task) 
     { 
      bool isMatch = _IsEntityIdMatch(_TaskValue(task)) && 
       IsMatch(task.InviterId, task.RouteId, task.LuggageTypeId); 

      for (int i = 0; i < PriceDefinition.Rules.Count && isMatch == true; i++) 
      { 
       object value = task.GetFieldObjectValue(PriceDefinition.Rules[i].FieldName); 
       isMatch = PriceDefinition.Rules[i].IsMatch((value ?? string.Empty).ToString()); 
      } 
      return isMatch; 
     } 

     public bool IsMatch(long? entityId, Task3 task, long additionId) 
     { 
      return IsMatch(entityId ,task) && IsMatch(additionId); 
     } 
    } 

我也有3類使用默認的實現,實現IEntityPriceDefinition。這裏有兩個那些類的(第三個是相同的):

public class CustomerPriceDefinition : IEntityPriceDefinition, IDataEntity 
    { 
     private IEntityPriceDefinition _EntityPriceDefinition; 

     public virtual long PriceDefinitionId { get; set; } 
     public virtual long CustomerId { get; set; } 
     public virtual PriceDefinition PriceDefinition { get; set; } 

     public CustomerPriceDefinition() 
     { 
      _EntityPriceDefinition = new EntityPriceDefinition(
       PriceDefinition, 
       entityId => entityId.HasValue && entityId.Value == CustomerId, 
       t => t.CustomerId); 
     } 

     public bool IsMatch(long additionId) 
     { 
      return _EntityPriceDefinition.IsMatch(additionId); 
     } 

     public bool IsMatch(long? customerId, long? inviterId, long? routeId, long? luggageTypeId) 
     { 
      return _EntityPriceDefinition.IsMatch(customerId, inviterId, routeId, luggageTypeId); 
     } 

     public bool IsMatch(long? customerId, long? inviterId, long? routeId, long? luggageTypeId, 
      long additionId) 
     { 
      return _EntityPriceDefinition.IsMatch(customerId, inviterId, routeId, luggageTypeId, 
       additionId); 
     } 

     public bool IsMatch(long? customerId, Task3 task) 
     { 
      return _EntityPriceDefinition.IsMatch(customerId, task); 
     } 

     public bool IsMatch(long? customerId, Task3 task, long additionId) 
     { 
      return _EntityPriceDefinition.IsMatch(customerId, task, additionId); 
     } 
    } 

public class WorkerPriceDefinition : IEntityPriceDefinition, IDataEntity 
    { 
     private IEntityPriceDefinition _EntityPriceDefinition; 

     public virtual long PriceDefinitionId { get; set; } 
     public virtual long WorkerId { get; set; } 
     public virtual PriceDefinition PriceDefinition { get; set; } 

     public WorkerPriceDefinition() 
     { 
      _EntityPriceDefinition = new EntityPriceDefinition(
       PriceDefinition, 
       entityId => entityId.HasValue && entityId.Value == WorkerId, 
       t => t.WorkerId); 
     } 

     public bool IsMatch(long additionId) 
     { 
      return _EntityPriceDefinition.IsMatch(additionId); 
     } 

     public bool IsMatch(long? workerId, long? inviterId, long? routeId, long? luggageTypeId) 
     { 
      return _EntityPriceDefinition.IsMatch(workerId, inviterId, routeId, luggageTypeId); 
     } 

     public bool IsMatch(long? workerId, long? inviterId, long? routeId, long? luggageTypeId, 
      long additionId) 
     { 
      return _EntityPriceDefinition.IsMatch(workerId, inviterId, routeId, luggageTypeId, 
       additionId); 
     } 

     public bool IsMatch(long? workerId, Task3 task) 
     { 
      return _EntityPriceDefinition.IsMatch(workerId, task); 
     } 

     public bool IsMatch(long? workerId, Task3 task, long additionId) 
     { 
      return _EntityPriceDefinition.IsMatch(workerId, task, additionId); 
     } 
    } 

我也有倉庫接口和默認實現這些類:

public interface IEntityPriceDefinitionRepository<T> : IRepository<T> 
    where T : class, IEntityPriceDefinition, IDataEntity 
{ 
    IEnumerable<T> GetMatchPrices(
     Guid companyId, bool? isSuggested, bool? isValid, 
     long? entityId, long? inviterId, long? routeId, long? luggageTypeId, 
     Func<IQueryable<T>, IOrderedQueryable<T>> orderBy, 
     Expression<Func<T, object>>[] includes); 

    IEnumerable<T> GetMatchPrices(
     Guid companyId, bool? isSuggested, bool? isValid, 
     long? entityId, long? inviterId, long? routeId, long? luggageTypeId, long additionId, 
     Func<IQueryable<T>, IOrderedQueryable<T>> orderBy, 
     Expression<Func<T, object>>[] includes); 
} 

public class EntityPriceDefinitionRepository<T> : BaseRepository<T>, 
    IEntityPriceDefinitionRepository<T> where T : class,IEntityPriceDefinition, IDataEntity 
{ 
    private IEnumerable<T> GetMatchPrices(
     Guid companyId, bool? isSuggested, bool? isValid, 
     Expression<Func<T, bool>> isMatch, 
     Func<IQueryable<T>, IOrderedQueryable<T>> orderBy, 
     Expression<Func<T, object>>[] includes) 
    { 
     var filters = new Expression<Func<T, bool>>[]{ 
      x => x.PriceDefinition.CompanyId == companyId, 
      x => x.PriceDefinition.IsDeleted == false, 
      x => !isValid.HasValue || x.PriceDefinition.IsValid == isValid.Value, 
      x => !isSuggested.HasValue || x.PriceDefinition.IsSuggested == isSuggested.Value, 
      isMatch 
     }; 

     return GetQuery(filters, orderBy, includes); 
    } 

    public IEnumerable<T> GetMatchPrices(
     Guid companyId, bool? isSuggested, bool? isValid, 
     long? entityId, long? inviterId, long? routeId, long? luggageTypeId, 
     Func<IQueryable<T>, IOrderedQueryable<T>> orderBy, 
     Expression<Func<T, object>>[] includes) 
    { 
     return GetMatchPrices(companyId, isSuggested, isValid, 
     ////////////////// THIS CAUSE THE EXCEPTION MENTIONED BELOW: ////////////////// 
      x => x.IsMatch(entityId, inviterId, routeId, luggageTypeId), 
      orderBy, includes); 
    } 

    public IEnumerable<T> GetMatchPrices(
     Guid companyId, bool? isSuggested, bool? isValid, 
     long? entityId, long? inviterId, long? routeId, long? luggageTypeId, long additionId, 
     Func<IQueryable<T>, IOrderedQueryable<T>> orderBy, 
     Expression<Func<T, object>>[] includes) 
    { 
     return GetMatchPrices(companyId, isSuggested, isValid, 
     ////////////////// THIS CAUSE THE EXCEPTION MENTIONED BELOW: ////////////////// 
      x => x.IsMatch(entityId, inviterId, routeId, luggageTypeId, additionId), 
      orderBy, includes); 
    }   
} 

及其類別庫類只是:

public class CustomerPriceDefinitionRepository : 
     EntityPriceDefinitionRepository<CustomerPriceDefinition> { } 

    public class WorkerPriceDefinitionRepository : 
     EntityPriceDefinitionRepository<WorkerPriceDefinition> { } 

當我調用CustomerPriceDefinitionRepository的GetMatchPrices方法時,會出現問題。它總是以有關上述標記方法異常結束:

LINQ實體無法識別方法「布爾IsMatch(System.Nullable 1[System.Int64], System.Nullable 1 [System.Int64],System.Nullable 1[System.Int64], System.Nullable 1 [系統。 Int64])'方法,並且此方法不能轉換爲商店表達式。

拉吉斯拉夫Mrnka的回答我here使用模型中定義的功能,但我想我所有的代碼是在它的類,而不是在XML的。另外,這段代碼與edmx使用的巨大範圍無關。此外,我相信爲了使用模型定義的函數,我將不得不定義3個方法 - 每個IEntityPriceDefinition子類的一個IsMatch。

我真的不知道如何解決這個問題,這種情況下最好的解決方案是什麼,特別是對於這樣的非簡單結構。我會appriciate任何幫助。

+0

正如其他許多人已經告訴你的,問題是'.IsMatch'沒有SQL等價物,因此**不能被**轉換成Linq-to-Entities的有效SQL語句。所以你需要找到另一種表達這種情況的方式,例如使用'.StartsWith()'或其他東西。 ** OR:**您需要從數據庫中檢索沒有該表達式的所有實體,並且只使用Linq-to-objects過濾應用內存中的這些實體。 – 2011-05-02 05:17:03

+0

@marc_s:我明白了這個問題,我正在尋找解決問題的最佳方法。八,現在我不知道該怎麼做。 – Naor 2011-05-02 09:17:38

+0

如果您正在使用SQL Server,是否可以將IsMatch作爲SQLCLR函數編寫,然後將其用作edmx的導入函數? – Menahem 2011-05-02 12:45:10

回答

1

我EntityPriceDefinition添加靜態方法:

public static Expression<Func<CustomerPriceDefinition, bool>> IsMatchExpression(
     long? entityId, long? inviterId, long? routeId, long? luggageTypeId, long additionId) 
    { 
     return x => 
      (entityId.HasValue && entityId.Value == x.CustomerId) && 
      (inviterId.HasValue || routeId.HasValue || luggageTypeId.HasValue) && 
      !(
       (x.PriceDefinition.InviterId.HasValue && inviterId.HasValue && 
        x.PriceDefinition.InviterId.Value != inviterId.Value) || 

       (x.PriceDefinition.LuggageTypeId.HasValue && luggageTypeId.HasValue && 
        x.PriceDefinition.LuggageTypeId.Value != luggageTypeId.Value) || 

       (x.PriceDefinition.InviterId.HasValue && inviterId.HasValue && 
        x.PriceDefinition.InviterId.Value != inviterId.Value) 
      ) && 
      x.PriceDefinition.AdditionsPrices.Any(a => a.AdditionId == additionId); 
    } 

這樣的表達式知道如何將它來查詢。