是否有一种很好的方法可以在不引入对Entity Framework / System.Data.Entity.dll的依赖的情况下利用EdmFunctionAttribute
?
我以为我可以拥有一个方法和一个具体实现的接口,该实现使用EdmFunctionAttribute
将它映射到数据库函数来实现该方法。
我在程序集中定义了上下文接口IMyContext
,在另一个程序集中定义了实体框架实现MyContext
。
public interface IMyContext
{
double SomeFunction(double first, double second);
// other interface details here
}
public partial class MyContext : IMyContext
{
[EdmFunction("MyNamespace", "MyDatabaseFunction")]
public double SomeFunction(double first, double second)
{
throw new NotSupportedException("This method may only be called as part of a LINQ expression.");
}
// rest of interface implementation here
}
我使用工厂(在幕后使用StructureMap)来获取上下文实例作为接口类型:
using (IMyContext context = ContextFactory.GetNewContext())
{
var results = context.Table.Select(t => context.SomeFunction(t.Col1, t.Col2)).ToList();
}
这会抛出一个NotSupportException
,说LINQ to Entities无法识别方法'Double SomeFunction(Double,Double)'。
如果我将上下文转换为具体实现
using (MyContext context = ContextFactory.GetNewContext() as MyContext)
{
...
}
然后它可以工作,但是我需要指定具体的实现,我不想这样做。
该函数不必是上下文类的成员,我只是把它放在那里进行探索。
答案 0 :(得分:1)
您是否可以使用Generic Repository Pattern并在其中公开IQueryable
接口,例如:
IQueryable FindAll(Func<T,bool> exp);
答案 1 :(得分:0)
这是不可能的,因为Linq查询构建器将调查接口类型而不是具体类。表达式树将包含接口方法的方法引用,当您调查方法的属性时,它不会返回任何属性。
您可以创建表达式访问者并访问表达式树,并将类型从界面更改为具体类型。
TypeReplacer tr = new TypeReplacer();
tr.Visit(ex);
class TypeReplacer: ExpressionVisitor{
protected override MethodCallExpression MethodCall(MethodCallExpression exp)
{
// compare exp.Method and
// replace it with concrete Type's method
return exp;
}
}