如何解决将方法转换为linq到实体表达式以查询实体框架
|| 我有这个问题,我真的不知道如何解决。在放弃这个问题之前,我问了两个问题,但没有为我的情况找到正确的答案。这是详细的问题。 我有一个接口和默认实现: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? 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? 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? luggageTypeId)
{
return _IsEntityIdMatch(entityId) && IsMatch(inviterId,routeId,luggageTypeId);
}
public bool IsMatch(long? entityId,long additionId)
{
return IsMatch(entityId,inviterId,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,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? luggageTypeId)
{
return _EntityPriceDefinition.IsMatch(customerId,luggageTypeId);
}
public bool IsMatch(long? customerId,long additionId)
{
return _EntityPriceDefinition.IsMatch(customerId,luggageTypeId,additionId);
}
public bool IsMatch(long? customerId,Task3 task)
{
return _EntityPriceDefinition.IsMatch(customerId,task);
}
public bool IsMatch(long? 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? luggageTypeId)
{
return _EntityPriceDefinition.IsMatch(workerId,luggageTypeId);
}
public bool IsMatch(long? workerId,long additionId)
{
return _EntityPriceDefinition.IsMatch(workerId,additionId);
}
public bool IsMatch(long? workerId,Task3 task)
{
return _EntityPriceDefinition.IsMatch(workerId,task);
}
public bool IsMatch(long? workerId,additionId);
}
}
我还为这些类提供了存储库接口和默认实现:
public interface IEntityPriceDefinitionRepository<T> : IRepository<T>
where T : class,IEntityPriceDefinition,IDataEntity
{
IEnumerable<T> GetMatchPrices(
Guid companyId,bool? isSuggested,bool? isValid,long? entityId,Func<IQueryable<T>,IOrderedQueryable<T>> orderBy,Expression<Func<T,object>>[] includes);
IEnumerable<T> GetMatchPrices(
Guid companyId,long additionId,object>>[] includes);
}
public class EntityPriceDefinitionRepository<T> : BaseRepository<T>,IEntityPriceDefinitionRepository<T> where T : class,IDataEntity
{
private IEnumerable<T> GetMatchPrices(
Guid companyId,bool>> isMatch,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,object>>[] includes)
{
return GetMatchPrices(companyId,isSuggested,isValid,////////////////// THIS CAUSE THE EXCEPTION MENTIONED BELOW: //////////////////
x => x.IsMatch(entityId,luggageTypeId),additionId),includes);
}
}
而类存储库类就是:
public class CustomerPriceDefinitionRepository :
EntityPriceDefinitionRepository<CustomerPriceDefinition> { }
public class WorkerPriceDefinitionRepository :
EntityPriceDefinitionRepository<WorkerPriceDefinition> { }
当我调用CustomerPriceDefinitionRepository \的GetMatchPrices方法时,发生了问题。关于上面标记的方法,它总是以异常结束:
LINQ to Entities无法识别方法\'Boolean IsMatch(System.Nullable1[System.Int64],System.Nullable
1[System.Int64],System.Nullable1[System.Int64],System.Nullable
1[System.Int64])\',并且该方法无法转换为商店表达式。
Ladislav Mrnka在这里回答我使用模型定义的函数,但我希望所有代码都在其类中,而不是xml中。此外,此代码与edmx使用的巨大范围无关。另外,我相信,为了使用模型定义的函数,我将必须定义3种方法-每个IEntityPriceDefinition子类一个IsMatch。
我真的不知道如何解决这个问题,对于这种情况,尤其是对于这种非简单结构,什么是最佳解决方案?我会寻求任何帮助。
解决方法
我在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);
}
这样,表达式便知道如何将其转换为查询。