Câu trả lời:
Bạn cần bật nó lên theo cách bạn nghĩ về nó. Thay vì thực hiện "vào" để tìm quyền người dùng của mặt hàng hiện tại trong một bộ quyền người dùng được xác định trước, bạn đang hỏi một bộ quyền người dùng được xác định trước nếu nó có chứa giá trị áp dụng của mặt hàng hiện tại. Điều này chính xác giống như cách bạn sẽ tìm thấy một mục trong danh sách thông thường trong .NET.
Có hai cách để thực hiện việc này bằng LINQ, một cách sử dụng cú pháp truy vấn và cách khác sử dụng cú pháp phương thức. Về cơ bản, chúng giống nhau và có thể được sử dụng thay thế cho nhau tùy theo sở thích của bạn:
Cú pháp truy vấn:
var selected = from u in users
where new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights)
select u
foreach(user u in selected)
{
//Do your stuff on each selected user;
}
Phương pháp Cú pháp:
var selected = users.Where(u => new[] { "Admin", "User", "Limited" }.Contains(u.User_Rights));
foreach(user u in selected)
{
//Do stuff on each selected user;
}
Sở thích cá nhân của tôi trong trường hợp này có thể là cú pháp phương thức vì thay vì gán biến, tôi có thể thực hiện foreach qua một cuộc gọi ẩn danh như thế này:
foreach(User u in users.Where(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
Về mặt cú pháp, điều này có vẻ phức tạp hơn và bạn phải hiểu khái niệm biểu thức lambda hoặc đại biểu để thực sự tìm hiểu điều gì đang xảy ra, nhưng như bạn có thể thấy, điều này làm cô đọng một số tiền hợp lý.
Tất cả đều thuộc về phong cách và sở thích mã hóa của bạn - cả ba ví dụ của tôi đều làm điều tương tự hơi khác nhau.
Một cách khác thậm chí không sử dụng LINQ, bạn có thể sử dụng cú pháp phương thức tương tự thay thế "where" bằng "FindAll" và nhận được kết quả tương tự, cũng sẽ hoạt động trong .NET 2.0:
foreach(User u in users.FindAll(u => new [] { "Admin", "User", "Limited" }.Contains(u.User_Rights)))
{
//Do stuff on each selected user;
}
Điều này sẽ đủ mục đích của bạn. Nó so sánh hai bộ sưu tập và kiểm tra xem một bộ sưu tập có các giá trị khớp với các bộ sưu tập trong bộ sưu tập khác không
fea_Features.Where(s => selectedFeatures.Contains(s.feaId))
Nếu bạn đang sử dụng VS2008 / .net 3.5, hãy xem mẹo số 8 của Alex James: http://bloss.msdn.com/alexj/archive/2009/03/26/tip-8-wr-where-in-style -queries-using-linq-to-entity.aspx
Nếu không, chỉ sử dụng phương thức Array.Contains (someEntity.Member).
Tôi sẽ tham gia Nội tại trong bối cảnh này. Nếu tôi đã sử dụng có chứa, nó sẽ lặp lại 6 lần mặc dù thực tế là chỉ có một trận đấu.
var desiredNames = new[] { "Pankaj", "Garg" };
var people = new[]
{
new { FirstName="Pankaj", Surname="Garg" },
new { FirstName="Marc", Surname="Gravell" },
new { FirstName="Jeff", Surname="Atwood" }
};
var records = (from p in people join filtered in desiredNames on p.FirstName equals filtered select p.FirstName).ToList();
Giả sử tôi có hai đối tượng danh sách.
List 1 List 2
1 12
2 7
3 8
4 98
5 9
6 10
7 6
Sử dụng Chứa, nó sẽ tìm kiếm từng mục Danh sách 1 trong Danh sách 2 có nghĩa là việc lặp lại sẽ xảy ra 49 lần !!!
Tôi cũng đã cố gắng làm việc với một thứ giống như SQL-IN - truy vấn theo Mô hình dữ liệu thực thể . Cách tiếp cận của tôi là một trình xây dựng chuỗi để soạn một biểu thức OR lớn. Điều đó thật tồi tệ, nhưng tôi sợ đó là cách duy nhất để đi ngay bây giờ.
Bây giờ, có vẻ như thế này:
Queue<Guid> productIds = new Queue<Guid>(Products.Select(p => p.Key));
if(productIds.Count > 0)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}.ProductId = Guid\'{1}\'", entities.Products.Name, productIds.Dequeue());
while(productIds.Count > 0)
{
sb.AppendFormat(" OR {0}.ProductId = Guid\'{1}\'",
entities.Products.Name, productIds.Dequeue());
}
}
Làm việc với GUID trong ngữ cảnh này : Như bạn có thể thấy ở trên, luôn có từ "GUID" trước chính GUID trong các đoạn chuỗi truy vấn. Nếu bạn không thêm cái này, hãy ObjectQuery<T>.Where
ném ngoại lệ sau:
Các loại đối số 'Edm.Guid' và 'Edm.String' không tương thích với thao tác này., Gần biểu thức bằng, dòng 6, cột 14.
Tìm thấy điều này trong Diễn đàn MSDN, có thể hữu ích để ghi nhớ.
Matthias
... mong chờ phiên bản tiếp theo của .NET và Entity Framework, khi mọi thứ trở nên tốt hơn. :)
Một phương pháp khác để trả lời BenAlabaster
Trước hết, bạn có thể viết lại truy vấn như thế này:
var matches = from Users in people
where Users.User_Rights == "Admin" ||
Users.User_Rights == "Users" ||
Users.User_Rights == "Limited"
select Users;
Chắc chắn điều này là 'nhiều từ' và một nỗi đau để viết nhưng nó hoạt động như nhau.
Vì vậy, nếu chúng ta có một số phương thức tiện ích giúp dễ dàng tạo các loại biểu thức LINQ này, chúng ta sẽ kinh doanh.
với một phương thức tiện ích tại chỗ, bạn có thể viết một cái gì đó như thế này:
var matches = ctx.People.Where(
BuildOrExpression<People, string>(
p => p.User_Rights, names
)
);
Điều này xây dựng một biểu thức có tác dụng tương tự như:
var matches = from p in ctx.People
where names.Contains(p.User_Rights)
select p;
Nhưng điều quan trọng hơn thực sự hoạt động đối với .NET 3.5 SP1.
Đây là chức năng hệ thống ống nước làm cho điều này có thể:
public static Expression<Func<TElement, bool>> BuildOrExpression<TElement, TValue>(
Expression<Func<TElement, TValue>> valueSelector,
IEnumerable<TValue> values
)
{
if (null == valueSelector)
throw new ArgumentNullException("valueSelector");
if (null == values)
throw new ArgumentNullException("values");
ParameterExpression p = valueSelector.Parameters.Single();
if (!values.Any())
return e => false;
var equals = values.Select(value =>
(Expression)Expression.Equal(
valueSelector.Body,
Expression.Constant(
value,
typeof(TValue)
)
)
);
var body = equals.Aggregate<Expression>(
(accumulate, equal) => Expression.Or(accumulate, equal)
);
return Expression.Lambda<Func<TElement, bool>>(body, p);
}
Tôi sẽ không cố gắng giải thích phương thức này, ngoài việc nói rằng về cơ bản nó xây dựng một biểu thức vị ngữ cho tất cả các giá trị bằng cách sử dụng valueSelector (tức là p => p.User_Rights) và OR các vị từ đó cùng nhau tạo ra một biểu thức cho hoàn thành Thuộc tính
Ví dụ thực tế:
var trackList = Model.TrackingHistory.GroupBy(x => x.ShipmentStatusId).Select(x => x.Last()).Reverse();
List<int> done_step1 = new List<int>() {2,3,4,5,6,7,8,9,10,11,14,18,21,22,23,24,25,26 };
bool isExists = trackList.Where(x => done_step1.Contains(x.ShipmentStatusId.Value)).FirstOrDefault() != null;
Nghiêm túc? Bạn chưa bao giờ sử dụng
where (t.MyTableId == 1 || t.MyTableId == 2 || t.MyTableId == 3)
Checks = NumValues * NumRows
. Bởi vì đây là phép tính loại M * N, nếu một trong hai là nhỏ thì thời gian để thực hiện mỗi kiểm tra cần thiết cũng sẽ nhỏ. Tôi đã thêm các ràng buộc để cjm30305 biết cách thiết lập môi trường thử nghiệm trong đó cho thấy lý do tại sao giải pháp của anh ta kém.
where new[] { 1, 2, 3 }.Contains(x)
ít so sánh hơn where (x == 1 || x == 2 || x == 3)
không?