问题描述
我有一个实现 IComparable
的POCO类.
I have a POCO class that implements IComparable
.
public interface IEntity : IComparable
{
long Id { get; set; }
Func<IEntity, bool> CompareFunction { get; }
}
public abstract class BaseEntity : IEntity
{
public virtual long Id { get; set; }
public Func<IEntity, bool> CompareFunction
{
get
{
Func<IEntity, bool> compare = EvaluateEquivalency;
return compare;
}
}
public static int Compare(BaseEntity left, BaseEntity right)
{
if (object.ReferenceEquals(left, right))
{
return 0;
}
if (object.ReferenceEquals(left, null))
{
return -1;
}
return left.CompareTo(right);
}
public static bool operator ==(BaseEntity left, BaseEntity right)
{
if (object.ReferenceEquals(left, null))
{
return object.ReferenceEquals(right, null);
}
return left.Equals(right);
}
public static bool operator !=(BaseEntity left, BaseEntity right)
{
return !(left == right);
}
public static bool operator <(BaseEntity left, BaseEntity right)
{
return Compare(left, right) < 0;
}
public static bool operator >(BaseEntity left, BaseEntity right)
{
return Compare(left, right) > 0;
}
public override bool Equals(object obj)
{
IEntity other;
if (!(obj is IEntity)) return false;
other = (IEntity)obj;
if (object.ReferenceEquals(other, null))
{
return false;
}
return this.CompareTo(other) == 0;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public virtual int CompareTo(object obj)
{
if (obj == null) throw new ArgumentNullException("obj");
if (!(obj is IEntity)) throw new ArgumentException("obj is not an IEntity");
if (this.Id == ((IEntity)obj).Id) return 0;
return -1;
}
private bool EvaluateEquivalency(IEntity toCompare)
{
return Equals(toCompare);
}
}
我的 DbContext
中的POCO类有 DbSet
.
There is DbSet
for my POCO class in my DbContext
.
但是,当我执行 BaseRepository.Exists()
时,我得到的是 System.NotSupportedException
.
However, when I execute BaseRepository.Exists()
I get a System.NotSupportedException
.
public class BaseRepository<TEntity> : IRepository<TEntity> where TEntity : class, IEntity
{
...
private TEntity Exists(TEntity entity)
{
return Context.DbSet<TEntity>.FirstOrDefult(i => i.CompareTo(entity) == 0);
}
private TEntity ExistsV2(TEntity entity)
{
return Context.DbSet<TEntity>.FirstOrDefult(i => i.CompareFunction(entity) == 0);
}
...
}
异常堆栈跟踪看起来像...
The exception stack trace looks like...
System.NotSupportedException was unhandled by user code
Message=Unable to create a constant value of type '{My POCO Class}'. Only primitive types or enumeration types are supported in this context.
Source=System.Data.Entity
StackTrace:
at System.Data.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.EqualsTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.FirstPredicateTranslatorBase.Translate(ExpressionConverter parent, MethodCallExpression call)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.Convert()
at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__1[TResult](IEnumerable`1 sequence)
at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
at System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
当我执行 BaseRepository.ExistsV2()
时,我会得到略有不同的 System.NotSupportedException
.
When I execute BaseRepository.ExistsV2()
I get a slightly different System.NotSupportedException
.
System.NotSupportedException was unhandled by user code
HResult=-2146233067
Message=The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
Source=System.Data.Entity
StackTrace:
at System.Data.Objects.ELinq.ExpressionConverter.NotSupportedTranslator.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.FirstPredicateTranslatorBase.Translate(ExpressionConverter parent, MethodCallExpression call)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod)
at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Objects.ELinq.ExpressionConverter.Convert()
at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__1[TResult](IEnumerable`1 sequence)
at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
at System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
我已经读过实体框架不支持 IComparable
吗?无论如何还是有人知道该功能是否可以在EF6中使用?
I've read the Entity Framework doesn't support IComparable
? Is there anyway around this or does anyone know whether the functionality will be available in EF6?
推荐答案
不,您不能这样做.
EF要求所有操作都能够执行100%服务器端.要支持 IComparable
或 IEquatable
,将要求EF能够将任意IL转换为SQL,但这尚无法做到.
EF requires all operations to be able to execute 100% server-side. Supporting IComparable
or IEquatable
would require EF to be able to translate arbitrary IL into SQL, which it can't yet do.
否则,它必须将整个未过滤的结果集传递给客户端.您可以通过使用 AsEnumerable()
:
Otherwise, it would have to pass the entire unfiltered result set to the client. You can achieve exactly this by using AsEnumerable()
:
Context.DbSet<TEntity>.AsEnumerable().FirstOrDefault(i => i.CompareTo(entity) == 0);
这当然会运行得很慢,因此,如果表的大小很大,我不建议这样做.
This will of course run quite slow though, so I wouldn't recommend it if the table is of any significant size.
这篇关于是否可以使用IComparable在Entity Framework中比较实体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!