2016-03-03 14 views
12

Tôi có một thiết lập cơ sở dữ liệu bằng cách sử dụng 'nhân rộng chủ/nô lệ'. Tôi có một bản chính và (ít nhất) một nô lệ, có thể là nô lệ. Để đơn giản từ đây tôi sẽ nói về một chủ, một nô lệ vì xác định nô lệ để sử dụng bao gồm một số logic nghiệp vụ không liên quan đến vấn đề thực tế trong tầm tay.Cách đạt được sự tách đọc/ghi với Entity Framework

Dưới đây là một sơ đồ của các thiết lập (với nô lệ ℕ):

Overview

Trong ứng dụng (hiện đang sử dụng Dapper) Tôi có những điều sau đây, đơn giản hóa, mã:

abstract class BaseRepo 
{ 
    private readonly string _readconn; 
    private readonly string _writeconn; 

    public BaseRepo(string readConnection, string writeConnection) 
    { 
     _readconn = readConnection;  //Actually IEnumerable<string> for ℕ slaves 
     _writeconn = writeConnection; 
    } 

    private SqlConnection GetOpenConnection(string cnstring) 
    { 
     var c = new SqlConnection(cnstring); 
     c.Open(); 
     return c; 
    } 

    public SqlConnection GetOpenReadConnection() 
    { 
     return this.GetOpenConnection(_readconn); 
     // Actually we use some business-logic to determine *which* of the slaves to use 
    } 

    public SqlConnection GetOpenWriteConnection() 
    { 
     return this.GetOpenConnection(_writeconn); 
    } 
} 

class CustomerRepo : BaseRepo 
{ 
    // ...ctor left out for brevity... 

    // "Read" functions use the "read" connection 
    public IEnumerable<Customer> ListCustomers() 
    { 
     using (var c = this.GetOpenReadConnection()) 
     { 
      return c.Query<Customer>("select * from customers order by name") 
        .AsEnumerable(); 
     } 
    } 

    // "Write" functions use the "write" connection 
    public void UpdateCustomer(Customer cust) 
    { 
     using (var c = this.GetOpenWriteConnection()) 
     { 
      c.Execute("update customers set name = @name where id = @id", cust); 
     } 
    } 
} 

My câu hỏi là; giả sử tôi muốn sử dụng Entity Framework ("mã đầu tiên", nên có liên quan) thay vì Dapper; làm thế nào tốt nhất tôi nên đi về việc đạt được cùng một khái niệm; chèn/cập nhật/xóa được thực hiện đối với cơ sở dữ liệu "chính" và các lựa chọn được thực hiện đối với một nô lệ (hoặc bất kỳ nô lệ nào). EF có hỗ trợ kịch bản này không? Tôi cần phải làm gì để thực hiện công việc này?


thông tin bổ sung: Tôi đã sử dụng 'read-only' và 'viết chỉ của người sử dụng ở cấp SQL Server như một 'dòng cuối cùng của quốc phòng' để ngăn chặn bất kỳ sai lầm trong Dal. Những gì tôi đang tìm kiếm là một phương pháp hạn chế DAL của tôi để tránh phải bắt các ngoại lệ của SQL Server vì các hành động 'không được phép' và phải đi đến máy chủ SQL (không chính xác) ngay từ đầu trước khi tìm ra hành động mong muốn không cho phép. Tôi có thể sử dụng cách tiếp cận tương tự như tôi làm ngay bây giờ; khởi tạo/sử dụng đúng DbContext trong chính phương thức đó (listcustomers/updatecustomer trong ví dụ trên). Tôi hiểu rồi. Nhưng điều đó có nghĩa là tôi phải tạo ra một chức năng 'wrapper' cho mỗi hành động "CRUD" trên mỗi "thực thể", đó là lý do tại sao tôi đã chuyển từ EF sang EF ngay từ đầu; chỉ đơn giản là phơi bày một DBSet và có EF chăm sóc các truy vấn thay đổi/SQL vv và bây giờ, hy vọng, cũng tìm ra chuỗi kết nối để sử dụng cho mỗi hành động.

+0

Cách đơn giản nhất tôi đoán là cung cấp các chuỗi kết nối khác nhau cho từng loại tình huống. Vì vậy, một giải pháp mà không phải là ở cấp độ của Entity Framework mà là ở cấp độ của SQL. PS. Vui lòng tiếp tục sử dụng công cụ phóng đại, chúc mừng – misha130

+1

@ misha130 Bạn có thể làm rõ? Bạn sẽ định nghĩa "loại tình huống" là gì? Và bạn sẽ định nghĩa cái gì là "trên đòn bẩy của chính SQL"? – RobIII

+1

Bạn thực sự cần thay đổi chuỗi kết nối khi chạy. Entity Framework cung cấp cơ sở này. Câu hỏi này sẽ cho bạn thấy làm thế nào! http://stackoverflow.com/questions/22267949/entity-framework-change-connection-string-at-runtime – Gusdor

Trả lời

1

Theo đề xuất của người khác, tạo ngữ cảnh đọc/ghi theo mặc định và sau đó tạo một ngữ cảnh chỉ đọc được kế thừa từ ngữ cảnh đó. Ngoài ra, hãy đảm bảo triển khai thực hiện trong một lớp học một hàm tạo chấp nhận cấu hình khác nếu bạn muốn.

public partial class CustomerEntities : DbContext 
{ 
    protected CustomerEntities(string nameOrConnectionString):base(nameOrConnectionString) 
    {   
    } 
} 

public class ReadonlyCustomerEntities : CustomerEntities 
{ 
    public ReadonlyCustomerEntities() 
     : base("name=ReadonlyCustomerEntities") 
    {   
    } 

    public override int SaveChanges() 
    { 
     // Throw if they try to call this 
     throw new InvalidOperationException("This context is read-only."); 
    } 
}