2012-01-28 32 views
5

Tôi khá chắc chắn tôi biết câu trả lời là không nhưng như một nỗ lực mương cuối cùng tôi nghĩ rằng tôi muốn hỏi câu hỏi ở đây.Có thể sửa đổi một biểu thức IQueryable theo cách thủ công

Tôi đang sử dụng mã EF đầu tiên để truy vấn một bảng trong thời trang thường

_context.Set<Foo>().Where(f => f.Bar == 999); 

mà tạo ra các biểu thức sau đây (Tôi vừa mới viết này để nó có thể là sai).

{SELECT 
[Extent1].[Test] AS [Test], 
[Extent1].[Test2] AS [Test2], 
FROM [dbo].[Foo] AS [Extent1] 
WHERE 19 = [Extent1].[Bar]} 

Bây giờ, có thể tự sửa đổi truy vấn này để thay đổi tên bảng thành Foo10 không? (có thể không)

Nếu không, có ai biết cách tôi có thể "kết thúc muộn" tên bảng trong mã trước không?

Có thể bạn đang tự hỏi "Tại sao lại bị hack bẩn?" Như thường lệ, đây là vấn đề cũ với cơ sở dữ liệu có một số vấn đề về thiết kế và không thể thay đổi.

Xin cảm ơn trước.

Ps. Tôi biết rằng tôi có thể sử dụng Database.SqlQuery nhưng không muốn.

+0

tại sao bạn không có bảng 'Foo10' trong mô hình của mình? – BrokenGlass

+0

Bởi vì về mặt kỹ thuật, cùng một mô hình của nó trải đều trên nhiều bảng. Bảng mà dữ liệu của bạn thay đổi tùy thuộc vào thông số –

+0

@mjmcloug, nó phụ thuộc như thế nào? – Krizz

Trả lời

0

Đây không phải là điều tôi muốn giới thiệu nhưng bạn có thể ToString() truy vấn để đặt câu lệnh SQL vào một biến sau đó chuỗi thay thế tên bảng. Sau đó, SQL thực hiện SQL đó?

Có mùi và bị hack nhưng có thể?

+0

Theo tôi biết, chỉ có thể nếu bạn sẵn sàng vứt bỏ việc sử dụng Khung thực thể - điều đó có nghĩa là bạn cũng có thể viết SQL bằng tay. – Bevan

+0

Tôi đã nghĩ đến việc này. Có khả năng dữ liệu này sẽ chỉ đọc để có thể phù hợp. Hãy suy nghĩ của nó một chút tinh ranh mặc dù: D –

+0

@ Bevan nó không phải là một tổng số chất thải. Nó có nghĩa là chúng ta có thể xây dựng biểu thức theo cách thông thường và thay đổi nó vào phút cuối thay vì có một truy vấn sql mới cho mỗi mệnh đề where chúng ta muốn –

1

Giả sử bạn có số lượng bảng hợp lý, tôi sẽ thêm tất cả vào mô hình và tạo giao diện chung tất cả các lớp sẽ triển khai và sau đó chọn mô hình phù hợp và sử dụng Dynamic Linq để truy vấn.

Tôi không chắc chắn nếu làm việc này, đã không kiểm tra nó và chưa từng làm việc với "EF mã đầu tiên", nhưng đây là một cái gì đó tôi sẽ cố gắng:

Hãy nói rằng bảng của bạn (s) Foo có các trường - Bar, Pub, X và để X là bảng tương ứng phụ thuộc vào?

Sau đó, tôi sẽ xác định giao diện:

interface IFoo 
{ 
    int Bar { get; set; } 
    string Pub { get; set; } 
    int X { get; set; } 
} 

Sau đó, mỗi bảng sẽ có các lớp học trong mô hình:

[Table("Foo1")] 
class Foo1 : IFoo 
{ 
    public int Bar { get; set; } 
    public string Pub { get; set; } 
    public int X { get; set; } 
} 

[Table("Foo2")] 
class Foo2 : IFoo 
{ 
    public int Bar { get; set; } 
    public string Pub { get; set; } 
    public int X { get; set; } 
} 

Sau đó, bạn có thể lọc chúng như sau:

IQueryable GetAdequateFoo(int X) 
{ 
    switch (X) // you could use reflection here to dynamically call the given Set<Foo#>() 
    { 
     case 1: 
     return _context.Set<Foo1>(); 
     case 2: 
     return _context.Set<Foo2>(); 
     default: 
     return null; 
    } 
} 

IFoo GetFooByBarAndX(int bar, int X) 
{ 
    IQueryable context = GetAdequateFoo(X); 
    return context.Where("it.Bar == @0", bar).Cast<IFoo>(); 
} 

Nó chỉ là gợi ý không được kiểm tra và được viết từ đầu, xin vui lòng không bỏ phiếu nếu tôi sai và chỉ ra bất kỳ poten vấn đề về tial.

+0

Ha, tôi sẽ không bỏ phiếu cho câu trả lời này, nó thực sự là một ý tưởng khá thông minh để áp dụng một phương pháp nhà máy cho EF. Tôi sẽ không có một suy nghĩ mặc dù tôi cũng đã có các lớp bản đồ cũng như vậy nó rất nhiều lớp học để thiết lập này lên. Ý tưởng thông minh mặc dù! –

2

Tại sao bạn không sử dụng thừa kế TPT trên mô hình của mình?

Tương tự như câu trả lời của @ Krizz, nhưng bạn tránh sử dụng LINQ động.

Sử dụng nhận xét của bạn:

nếu một tham số đặc biệt có giá trị là 1 cái nhìn trong foo1 nếu 2 hình dáng của nó trong foo2 và vân vân

Vì vậy, bạn có thể làm điều này:

var query = ctx 
    .Foos 
    .OfMyType(value) 
    .Where(f => f.Bar == 999) // f.Bar is on the base/abstract entity. 
    .ToList(); 

đâu OfMyType là một phương pháp mở rộng tùy chỉnh trên IQueryable<T>:

public static IQueryable<T> OfMyType<T>(this IQueryable<T> source, string value) 
{ 
    switch (value) 
    { 
     case "1": 
     return source.OfType<Foo1>(); 
     case "2": 
     return source.OfType<Foo2>(); 
     // etc, etc 
    } 
} 

Hầu hết (nếu không phải tất cả) thuộc tính sẽ nằm trên thực thể trừu tượng "Foo" và bạn tạo các thực thể có nguồn gốc cho mỗi bảng, mỗi bảng có bảng sao lưu riêng. Bằng cách đó, "tiêu thụ" mã (ví dụ như những người tạo truy vấn), không cần quan tâm đến các bảng khác nhau/Foo, họ chỉ cần chuyển "giá trị ma thuật" vào kho của bạn (hy vọng bạn sử dụng), sau đó bạn có thể âm thầm chuyển sang bảng bạn muốn.

Điều đó có hiệu quả không?

+0

Một lần nữa điều này có vẻ tốt. Tôi sẽ phải cung cấp cho nó một đi và lấy lại cho bạn. Nhưng một lần nữa vấn đề duy nhất của tôi là nó tạo ra rất nhiều lớp mà tôi đang cố gắng tránh. Gotta yêu di sản! –

+1

+1 Rất tốt để đơn giản hóa cách tiếp cận của tôi bằng cách sử dụng những gì cung cấp khung. – Krizz

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