c# - LINQ 内的规范与 EF 4.3

标签 c# linq entity-framework-4 specification-pattern

我无意中尝试在 LINQ 查询中使用我的规范。这里的问题在于我对参数的规范。

让我们模拟一个简单的场景:

public class Car {
    public Guid Id { get; set; }
    public string Color { get; set; }
    public int UsedPieces { get; set; }
    // whatever properties
}

public class Piece {
    public Guid Id { get; set; }
    public string Color { get; set; }
    // whatever properties
}

public static class PieceSpecifications : ISpecification<Piece> {
    public static ISpecification<Piece> WithColor(string color) {
        return new Specification<Piece>(p => p.Color == color);
    }
}

我实际上想做什么

// Get accepts ISpecification and returns IQueryable<Car> to force just one call to database
var carWithPieces = _carRepository.Get(CarSpecifications.UsedPiecesGreaterThan(10));

var piecesWithColor = from p in _pieceRepository.Get()
                      let car = carWithPieces.FirstOrDefault() // entire query will does one call to database
                      where PieceSpecifications.WithColor(car.Color).IsSatisfiedBy(p) // unfortunately it isn't possible
                   // where p.Color == car.Color -> it works, but it's not what I want
                      select p;

我知道这有点令人困惑,但我试图避免在我的真实(大)场景中进行大量往返,而且我知道实际上不可能将原始 LINQ 与 Entity Framework 一起使用。我厌倦了尝试这么多博客和失败的(我的)方法。 有人知道一些真正好的方法。还有另一种方法吗?

错误

System.NotSupportedException: LINQ to Entities does not recognize the method 'Boolean IsSatisfiedBy(App.Model.Piece)' method, and this method cannot be translated into a store expression.

更新

基本规范模式

public class Specification<T> : ISpecification<T> {
    private readonly Expression<Func<T, bool>> _predicate;

    public Specification(Expression<Func<T, bool>> predicate) {
        _predicate = predicate;
    }

    public Expression<Func<T, bool>> Predicate {
        get { return _predicate; }
    }

    public bool IsSatisfiedBy(T entity) {
        return _predicate.Compile().Invoke(entity);
    }
}

更新

如果我这样做就很简单了

// call to database
var car = _carRepository
    .Get(CarSpecifications.UsedPiecesGreaterThan(10))
    .FirstOrDefault();

// Whoah! look I'm working, but calling to database again.
var piecesWithColor = _pieceRepository
    .Get(PieceSpecifications.WithColor(car.Color))
    .ToArray();

存储库

// The Get function inside repository accepts ISpecification<T>.
public IQueryable<T> Get(ISpecification<T> specification) {
    return Set.Where(specification.Predicate);
}

最佳答案

如果要在 LINQ-to-entities 查询中使用表达式,则不能编译和调用它。尝试直接使用 Predicate,因为 LINQ-to-entities 构建的表达式树由 EF LINQ 提供程序评估并转换为 SQL。

恕我直言,以这种方式使用规范没有意义。 LINQ-to-entities 查询是一个复合规范。因此,要么使用 Linq-to-entities,要么使用规范构建您自己的查询语言,让您的存储库将您的查询转换为 LINQ 查询。

关于c# - LINQ 内的规范与 EF 4.3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9709764/

相关文章:

c# - 在 C# 中创建分散行为

c# - 是否需要处理本地画笔变量?

c# - Linq 或 Tsql 'Pivot'

linq - IOrderedEnumerable 和防御性编程

c# - 异步 lambda 的执行有什么区别吗?

asp.net-mvc-3 - Entity Framework 检测到有冲突的更改。尝试插入多个具有相同键的实体时可能会发生这种情况

c# - 使用 lambda 表达式从 List<int> 中获取 N 个最大数字

c# - Gridview数据绑定(bind)下拉列表和更新

entity-framework - 当我在 EF4 代码中进行一对多映射时,是否可以隐藏我的 ICollection<T> 字段?

entity-framework-4 - Entity Framework 4.2枚举支持