Tôi tình cờ cố gắng sử dụng đặc tả của tôi bên trong truy vấn LINQ. Vấn đề ở đây là với đặc điểm kỹ thuật của tôi với các thông số.Đặc điểm kỹ thuật bên trong LINQ với EF 4.3
giả một kịch bản đơn giản Hãy:
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);
}
}
những gì tôi đang thực sự cố gắng để làm
// 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;
Tôi biết đó là một chút khó hiểu, nhưng tôi đang cố gắng để tránh được rất nhiều roundtrips bên trong kịch bản thực sự (lớn) của tôi và tôi biết rằng thực sự nó không thể làm bằng cách sử dụng LINQ thô với khung thực thể. Tôi cảm thấy mệt mỏi khi thử nhiều blog và phương pháp tiếp cận thất bại. Có người biết cách tiếp cận thực sự tốt. Có một cách khác để làm điều đó?
Lỗi
System.NotSupportedException: LINQ to Entities không nhận ra phương pháp 'Boolean IsSatisfiedBy (App.Model.Piece)' phương pháp, phương pháp và này không thể được dịch sang một biểu hiện cửa hàng .
CẬP NHẬT
cơ bản Thông số kỹ thuật Pattern
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);
}
}
CẬP NHẬT
Nó khá dễ dàng gọn gàng nếu tôi làm điều này
// 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();
Repository
// The Get function inside repository accepts ISpecification<T>.
public IQueryable<T> Get(ISpecification<T> specification) {
return Set.Where(specification.Predicate);
}
Bạn có thể giải thích những gì * IsSatisfiedBy (p) * làm không? – Aducci
Kiểm tra bài đăng của tôi, tôi đã cập nhật với triển khai thông số kỹ thuật đơn giản. –
Bạn nói đúng, bạn không thể làm được. LINQ không thông minh lắm để giải thích mã tùy chỉnh của bạn thành t-sql. Cho phép đợi .Net 4.5 và EF 5.0 với hỗ trợ enum (tính năng này kết nối với câu hỏi), chúng ta có thể thấy một số đường cú pháp mới. Tôi cũng rất thú vị. –