Tôi đã cố gắng cấu trúc lại một biểu thức LINQ thành một phương thức và đã chạy vào cả hai trường hợp ngoại lệ "Internal .NET Framework Data Provider error 1025.
" và "The parameter 'xyz' was not bound in the specified LINQ to Entities query expression.
".Không thể cấu trúc lại bằng LINQ to Entities và LinqKit/PredicateBuilder
Sau đây là các bộ phận liên quan của mô hình thực thể (sử dụng EF 4.2/LINQ to Entities):
public class Place : Entity
{
public string OfficialName { get; protected internal set; }
public virtual ICollection<PlaceName> { get; protected internal set; }
}
public class PlaceName : Entity
{
public string Text { get; protected internal set; }
public string AsciiEquivalent { get; protected internal set; }
public virtual Language TranslationTo { get; protected internal set; }
}
public class Language : Entity
{
public string TwoLetterIsoCode { get; protected internal set; }
}
Các mô hình quan hệ cơ bản là thế này:
Place (1) <-----> (0..*) PlaceName (0..*) <-----> (0..1) Language
tôi đang cố gắng để tạo ra một truy vấn sẽ, khi được tìm kiếm term
, hãy thử tìm các đối tượng Place
có OfficialName
bắt đầu bằng số term
HOẶC người có số PlaceName
có Text
hoặc AsciiEquivalent
bắt đầu với tìm kiếm term
. (Language
không phải là nơi tôi đang gặp rắc rối, mặc dù nó là một phần của truy vấn, vì PlaceName
s chỉ nên phù hợp cho CultureInfo.CurrentUICulture.TwoLetterIsoLanguageName
.)
Các mã sau không làm việc:
internal static IQueryable<Place> WithName(this IQueryable<Place> queryable,
string term)
{
var matchesName = OfficialNameMatches(term)
.Or(NonOfficialNameMatches(term));
return queryable.AsExpandable().Where(matchesName);
}
private static Expression<Func<Place, bool>> OfficialNameMatches(string term)
{
return place => place.OfficialName.StartsWith(term);
}
private static Expression<Func<Place, bool>> NonOfficialNameMatches(string term)
{
var currentLanguage = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
return place => place.Names.Any(
name =>
name.TranslationToLanguage != null
&&
name.TranslationToLanguage.TwoLetterIsoCode == currentLanguage
&&
(
name.Text.StartsWith(term)
||
(
name.AsciiEquivalent != null
&&
name.AsciiEquivalent.StartsWith(term)
)
)
);
}
Những gì tôi đang cố gắng làm tiếp theo là refactor phương pháp NonOfficialNameMatches
để trích xuất các biểu thức name => ...
ra thành một phương pháp riêng biệt, để nó có thể được tái sử dụng bởi các truy vấn khác. Dưới đây là một ví dụ tôi đã cố gắng, mà không hoạt động và ném ngoại lệ "The parameter 'place' was not bound in the specified LINQ to Entities query expression.
':
private static Expression<Func<Place, bool>> NonOfficialNameMatches(string term)
{
return place => place.Names.AsQueryable().AsExpandable()
.Any(PlaceNameMatches(term));
}
public static Expression<Func<PlaceName, bool>> PlaceNameMatches(string term)
{
var currentLanguage = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
return name =>
name.TranslationToLanguage != null
&&
name.TranslationToLanguage.TwoLetterIsoCode == currentLanguage
&&
(
name.Text.StartsWith(term)
||
(
name.AsciiEquivalent != null
&&
name.AsciiEquivalent.StartsWith(term)
)
);
}
Khi tôi không có chuỗi .AsExpandable()
trong NonOfficialNameMatches
, sau đó tôi nhận được' Internal .NET Framework Data Provider error 1025.
" ngoại lệ.
Tôi đã theo dõi other advice here chẳng hạn như một số kết hợp gọi .Expand()
trên các vị từ, nhưng luôn luôn kết thúc bằng một trong các ngoại lệ nói trên.
Thậm chí có thể đưa ra biểu thức này thành một phương pháp riêng biệt bằng cách sử dụng LINQ to Entities với LinqKit/PredicateBuilder không? Nếu có, làm thế nào? Tôi đang làm gì sai?
+100, cảm ơn bạn tôi đã bắt đầu nghĩ câu hỏi này sẽ không bao giờ được trả lời. Lời giải thích bổ sung cũng giúp ích. – danludwig