2008-12-30 40 views
7

Tôi có một LINQ to Entities truy vấn như thế này:LINQ trả về danh sách hoặc đơn đối tượng

var results = from r in entities.MachineRevision 
       where r.Machine.IdMachine == pIdMachine 
       && r.Category == (int)pCategory 
       select r; 

Thông thường, tôi sử dụng mã dưới đây để kiểm tra xem một số kết quả được trả về:

if (results.Count() > 0) 
{ 
    return new oMachineRevision(results.First().IdMachineRevision); 
} 

Tuy nhiên , Tôi nhận được NotSupportedException trong điều kiện nếu.

Thông báo lỗi là: Không thể tạo giá trị không đổi loại 'Loại đóng cửa'. Chỉ các kiểu nguyên thủy ('như Int32, String và Guid') mới được hỗ trợ trong ngữ cảnh này.

Lưu ý rằng pCategory là loại Enum.

Trả lời

11

EDIT: Dựa trên cập nhật của bạn, lỗi có thể liên quan đến một enum trong lớp thực thể của bạn. Hãy xem số blog entry để biết thêm thông tin và cách làm việc. Tôi để lại câu trả lời ban đầu của tôi như là một cải tiến về cú pháp truy vấn của bạn.

Thử thực hiện lựa chọn đối tượng đầu tiên trong chính truy vấn bằng FirstOrDefault và sau đó kiểm tra xem kết quả có rỗng không.

int compareCategory = (int)pCategory; // just a guess 
var result = (from r in entities.MachineRevision 
       where r.Machine.IdMachine == pIdMachine 
       && r.Category == compareCategory 
       select r).FirstOrDefault(); 

if (result != null) 
{ 
    return new oMachineRevision(result.IdMachineRevision); 
} 
+0

Vẫn không hoạt động, bởi vì chúng tôi đang cố gắng thực thi FirstOrDefault() phương pháp trên một đối tượng thực thể (đó là những gì được trả về bởi câu lệnh linq) và không phải là một IEnumerable –

+1

Chọn luôn trả về một IEnumerable, xem tài liệu ở đây http://msdn.microsoft.com/en-us/library/bb548891.aspx. Bạn có chắc chắn không mũ ví dụ là chính xác giống như mã của bạn? – tvanfosson

+0

Sai lầm của tôi, tôi xin lỗi vì điều đó. Để đơn giản hóa mã, tôi đã xóa một enum, giống như tvanfosson nhận thấy bởi thông báo lỗi tôi nhận được. Cảm ơn tất cả và xin lỗi vì đã gây hiểu lầm cho bạn. –

0

hãy thử sử dụng

IENumerable<MachineRevision> results = from r in entities.MachineRevision 
... 

để thay thế.

Tôi nghĩ rằng biến số đó gây ra sự cố của bạn.

+0

tôi đã cố gắng, và kết quả là như nhau :-( –

2

Tại sao không chỉ sử dụng FirstOrDefault() thay vào đó và kiểm tra giá trị rỗng? Tôi không thể thấy lợi ích trong việc truy vấn số lượng và sau đó lấy phần tử đầu tiên.

+0

tôi có thể thấy quan điểm của bạn. Tuy nhiên, nếu tôi sử dụng FirstOrDefault(), tôi vẫn nhận được rằng NotSupportedException, bởi vì tôi đang cố gắng thực hiện phương thức đó trên một đối tượng thực thể (đó là những gì được trả về bởi câu lệnh Linq), chứ không phải trên IEnumerable. –

0

Edit:

đọc được thông báo lỗi. "Không thể tạo giá trị không đổi của loại 'Loại đóng cửa'. Chỉ các kiểu nguyên thủy ('như Int32, String và Guid') mới được hỗ trợ trong ngữ cảnh này."

Một trong những so sánh này là với loại không phải là int, string hoặc guid. Tôi đoán Danh mục.

r.Machine.IdMachine == pIdMachine && r.Category == pCategory 

Điều thú vị là LinqToSql sẽ cho phép xây dựng này. Không biết tại sao LinqToEntities không hỗ trợ điều này.

1

Tôi không biết các đối tượng ẩn danh khác nhau sẽ được tạo tùy thuộc vào kết quả truy vấn. Tôi đoán họ chỉ muốn kết quả là loại IEnumerable

Làm thế nào để sử dụng foreach?

var results = from r in entities.MachineRevision 
       where r.Machine.IdMachine == pIdMachine 
       && r.Category == pCategory 
       select r; 

foreach(var r in results) 
{ 
    yield return new oMachineRevision(r.IdMachineRevision); 
} 
2

Trong việc triển khai tiêu chuẩn LINQ, các toán tử "chọn" và "ở đâu" ánh xạ tới các phương thức trả về IEnumerable hoặc IQueryable. Vì vậy, các phương thức linq tiêu chuẩn khi được sử dụng nên luôn trả về một IEnumerable từ truy vấn của bạn không phải là một đối tượng duy nhất.

Nhưng phương pháp LINQ là ứng cử viên cho các toán tử LINQ không bị hạn chế đối với các phương thức trả về IEnumerables, bất kỳ phương thức nào trả về bất kỳ thứ gì đều có thể được chọn. Trong trường hợp bạn có các phương thức ví dụ có tên "Chọn" và "Ở đâu" trả về một đối tượng hoặc các phương thức mở rộng cụ thể cho lớp của bạn và trả về một đối tượng duy nhất sẽ được sử dụng thay cho các đối tượng LINQ tiêu chuẩn.

Đoán của tôi là phương thức "Chọn" hoặc "Nơi" được xác định trong lớp của bạn đang làm cho LINQ trả về một giá trị duy nhất thay vì IEnumerable<T>.

0

Tôi nghĩ bạn cũng có thể chọn mục bạn muốn khác, cách đơn giản hơn bằng cách sử dụng biểu thức lambda.

var result = entities.MachineRevision 
       .Where(x => x.Machine.IdMachine == pIdMachine) 
       .Where(y => y.Category == (int)pCategory) 
       .FirstOrDefault(); 

if (result != null) 
{ 
    return new oMachineRevision(result.IdMachineRevision); 
} 

và sau đó tiến hành như bạn sẽ thường

+1

Không hoạt động, bởi vì ".Where (y => y.Category == (int) pCategory)" tạo ra lỗi. Bạn cần phải làm các diễn viên của Enum trước khi truy vấn. var iCategory = (int) pCategory; và sau đó chỉ sử dụng iCategory trong chính truy vấn. – derSteve

1

này áp dụng cho tất cả các loại tiềm ẩn quá. Tôi phải thừa nhận tôi tiếp tục quên điều này và đó là cách tôi đã xem qua bài đăng này.

nếu bạn có

class ClassA { 
       ... 

       private string value; 

       ... 

       public static implicit operator string(ClassA value) 
       { 
        return value.ToString(); 
       } 

       ... 
} 

bạn cần phải explictly đúc lớp để astring để so sánh.

vì vậy tôi thường làm điều này

var myClassAStr = myClassA.ToString(); 

    var x = (from a in entites where a.ValToCompare == myClassAStr select a).first(); 

// do stuff with x 
    ... 
+0

thực sự tôi thường sử dụng a.ValToCompare.Equals (myClassAstr) –

Các vấn đề liên quan