2013-04-25 33 views
5

Tôi hy vọng ai đó có thể giúp tôi, bởi vì có vẻ như tôi hoàn toàn bị mắc kẹt.Mã khuôn khổ thực thể Đầu tiên không có app.config

Đối với các dự án sắp tới trong công ty chúng tôi, chúng tôi muốn sử dụng Entity Framework 5 với phương pháp tiếp cận mã đầu tiên. Tôi chơi xung quanh một chút và mỗi khi tôi cố gắng sử dụng EF với các thư viện hiện có của chúng tôi, tôi thất bại vì có vẻ như EF phụ thuộc rất nhiều vào app.config hiện có.

Trong công ty chúng tôi có thư viện cơ sở dữ liệu cho phép chúng tôi kết nối với các nguồn dữ liệu và công nghệ cơ sở dữ liệu khác nhau tận dụng lợi thế của MEF (khung mở rộng được quản lý) cho các nhà cung cấp cơ sở dữ liệu. Tôi chỉ cần vượt qua một số cài đặt cơ sở dữ liệu, chẳng hạn như máy chủ (hoặc tệp), danh mục, thông tin người dùng và tên nhà cung cấp cơ sở dữ liệu, thư viện tìm plugin thích hợp và trả về cho tôi chuỗi kết nối tùy chỉnh hoặc IDbConnection. Chúng tôi muốn sử dụng thư viện này cùng với EF vì nó cho phép chúng tôi linh hoạt về cơ sở dữ liệu nào chúng tôi sử dụng cũng thay đổi cơ sở dữ liệu trong thời gian chạy.

So. Tôi thấy rằng một đối tượng DbContext điển hình không có tham số nào trong hàm tạo. Nó sẽ tự động tìm chuỗi kết nối thích hợp trong app.config. Chúng tôi không thích những thứ như vậy vì vậy tôi đã thay đổi constructor mặc định để có một đối tượng DbConnection được truyền cho lớp cơ sở DbContext. Không thỏa thuận.

Sự cố xảy ra khi mô hình mã đầu tiên thay đổi. EF tự động thông báo điều này và tìm kiếm các lớp/cấu hình di chuyển. Nhưng: Một lớp chuyển đổi điển hình yêu cầu một hàm tạo parameterless mặc định cho ngữ cảnh! Thật đáng tiếc!

Vì vậy, chúng tôi tạo lớp di chuyển của riêng mình bằng giao diện IDbContextFactory. Nhưng một lần nữa, có vẻ như cũng IDbContextFactory này cần một constructor parameterless, nếu không tôi không thể thêm di chuyển hoặc cập nhật cơ sở dữ liệu.

Hơn nữa, tôi đã tạo trình cấu hình di chuyển dữ liệu của riêng mình, trong đó tôi chuyển ngữ cảnh, cũng là cơ sở dữ liệu đích. Vấn đề là ở đây: Nó không tìm thấy bất kỳ lớp học di trú, không có vấn đề gì tôi cố gắng.

Tôi hoàn toàn bị kẹt vì dường như cách duy nhất để sử dụng EF là khi các chuỗi kết nối được lưu trong app.config. Và điều này là ngu ngốc vì chúng ta cần phải thay đổi các kết nối cơ sở dữ liệu trong thời gian chạy, và app.config là chỉ đọc cho người dùng mặc định!

Cách giải quyết vấn đề này?

+0

Nếu bạn không vượt qua trong chuỗi kết nối thì nó phải đọc nó từ app.config? Nếu không, làm thế nào nó có thể tìm thấy nó? –

Trả lời

3

Câu trả lời được cung cấp ở đây

https://stackoverflow.com/a/15919627/941240

Bí quyết là một chút thay đổi mặc định MigrateDatabaseToLatestVersion initializer để :

  • cơ sở dữ liệu luôn được khởi tạo ...
  • ... bằng cách sử dụng chuỗi kết nối từ ngữ cảnh hiện tại

DbMigrator sẽ vẫn tạo ngữ cảnh dữ liệu mới nhưng sẽ sao chép chuỗi kết nối từ ngữ cảnh của bạn theo trình khởi tạo. Tôi thậm chí còn có thể rút ngắn mã.

Và ở đây nó đi: Mã

public class MasterDetailContext : DbContext 
{ 
    public DbSet<Detail> Detail { get; set; } 
    public DbSet<Master> Master { get; set; } 

    // this one is used by DbMigrator - I am NOT going to use it in my code 
    public MasterDetailContext() 
    { 
     Database.Initialize(true); 
    } 

    // rather - I am going to use this, I want dynamic connection strings 
    public MasterDetailContext(string ConnectionString) : base(ConnectionString) 
    { 
     Database.SetInitializer(new CustomInitializer()); 
     Database.Initialize(true); 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
    } 
} 

public class CustomInitializer : IDatabaseInitializer<MasterDetailContext> 
{ 

    #region IDatabaseInitializer<MasterDetailContext> Members 

    // fix the problem with MigrateDatabaseToLatestVersion 
    // by copying the connection string FROM the context 
    public void InitializeDatabase(MasterDetailContext context) 
    {    
     Configuration cfg = new Configuration(); // migration configuration class 
     cfg.TargetDatabase = new DbConnectionInfo(context.Database.Connection.ConnectionString, "System.Data.SqlClient"); 

     DbMigrator dbMigrator = new DbMigrator(cfg); 
     // this will call the parameterless constructor of the datacontext 
     // but the connection string from above will be then set on in 
     dbMigrator.Update();    
    } 

    #endregion 
} 

Chủ đầu tư:

static void Main(string[] args) 
    { 

     using (MasterDetailContext ctx = new MasterDetailContext(@"Database=ConsoleApplication801;Server=.\SQL2012;Integrated Security=true")) 
     { 
     } 

     using (MasterDetailContext ctx = new MasterDetailContext(@"Database=ConsoleApplication802;Server=.\SQL2012;Integrated Security=true")) 
     { 
     } 
    } 

Chạy này sẽ gây ra hai cơ sở dữ liệu được tạo ra và di cư theo cấu hình di cư.

+0

Giải pháp tuyệt vời đã giải quyết được vấn đề của tôi một cách hoàn hảo. Thật kinh khủng khi tôi phải làm điều này mọi lúc cho mỗi ngữ cảnh - dường như Microsoft không nghĩ đến các kết nối cơ sở dữ liệu động và như vậy. – Atrotygma

+0

Tôi nhớ dành 3 hoặc 4 giờ để tìm ra điều đó. Điều tốt đẹp, tuy nhiên, là khi bạn cuối cùng đã có giải pháp thực tế, nó có vẻ khá đơn giản. –

+0

Tôi biết câu trả lời này đã được khoảng một thời gian, nhưng tôi nhận được một System.StackOverflowException khi tôi thực hiện nó. Dường như khi xây dựng một DbMigrator mới trong phương thức InitializeDatabase, hãy gọi hàm dựng mặc định của MasterDetailContext (theo các chú thích) và lời gọi tới 'Database.Initialize (true);' trong hàm dựng mặc định bằng cách nào đó gọi lại InitializeDatabase một lần nữa để nó bị kẹt trong một vòng lặp vô hạn. Tui bỏ lỡ điều gì vậy? – Kerby

0

Nó cần một hàm tạo tham số để gọi nó. Những gì bạn có thể làm là cung cấp mặc định của bạn DbConntectionFactory trong constructor rỗng, một cái gì đó như:

public DbContext() 
{ 
    IDbContextFactory defaultFactory; //initialize your default here 
    DbContext(defaultFactory); 
} 

public DbContext(IDbContextFactory factory) 
{ 
} 
Các vấn đề liên quan