2012-10-10 35 views
7

Tôi đang cố gắng để tạo ra một dbcontext cơ sở có chứa tất cả các đối tượng phổ biến mà sẽ luôn luôn được tái sử dụng trong nhiều dự án, như các trang, người sử dụng, vai trò, chuyển hướng, vvEF mã đầu tiên: dbcontext kế thừa tạo ra hai cơ sở dữ liệu

Khi làm như vậy, tôi có một lớp ContextBase kế thừa DbContext và định nghĩa tất cả các DbSets mà tôi muốn. Sau đó, tôi có một lớp Context kế thừa ContextBase, nơi tôi định nghĩa DbSets cụ thể của dự án. Các lớp học được quy định như sau:

public class ContextBase : DbContext 
{ 
    public virtual DbSet<User> Users { get; set; } 
    //more sets 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Configurations.Add(new UsersConfiguration()); 
     //add more configurations 
    } 
} 


public class Context : ContextBase 
{ 
    public DbSet<Building> Buildings { get; set; } 
    //some more project specific sets 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 
     modelBuilder.Configurations.Add(new BuildingsConfiguration()); 
     //add more project specific configs 
    } 
} 

Trong global.asax của tôi:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, Configuration>()); 

nơi Cấu hình referes đến một lớp kế thừa DbMigrationsConfiguration và trọng phương pháp Seed.

Hai lớp ngữ cảnh được định nghĩa trong cùng một không gian tên, nhưng lắp ráp chéo (để tôi có thể cập nhật dự án cơ sở trong nhiều dự án hiện có mà không cần chạm vào mã cụ thể của dự án) - không chắc chắn điều này có liên quan hay không.

MY VẤN ĐỀ: Khi chạy đoạn mã này, nó hoạt động tốt, nhưng khi nhìn vào cơ sở dữ liệu, nó thực sự tạo ra hai cơ sở dữ liệu khác nhau !! Một chứa tất cả các bảng thực thể cơ sở và một bảng chứa BOTH cơ sở và bảng tùy chỉnh. Hoạt động CRUD chỉ được thực hiện trên phiên bản tùy chỉnh (điều này rõ ràng là những gì tôi muốn), nhưng tại sao nó lại tạo ra lược đồ của một cái khác?

Bất kỳ trợ giúp nào được đánh giá cao, cảm ơn!

UPDATE:

Các mã sau đây là những gì tôi đã kết thúc với. Nó không phải là lý tưởng, nhưng nó hoạt động. Tôi vẫn muốn nhận được phản hồi về các cách để cải thiện điều này, nhưng trong thời gian chờ đợi, tôi hy vọng điều này sẽ giúp tiếp tục quá trình này. Tôi thực sự KHÔNG NGHỊ LÀM VIỆC NÀY! Nó là cực kỳ dễ bị lỗi và rất bực bội để gỡ lỗi. Tôi chỉ đơn thuần đăng bài này để xem liệu có bất kỳ ý tưởng hay triển khai nào tốt hơn để đạt được điều này hay không.

Vấn đề một (nhưng không phải là duy nhất) vẫn tồn tại là lượt xem MVC phải được thêm thủ công vào dự án. Tôi đã thêm nó vào gói Nuget, nhưng phải mất 2 đến 3 giờ để áp dụng gói nuget với rất nhiều tệp khi VS được kết nối với TFS. Với một số công việc khác và công cụ Chế độ xem tùy chỉnh, các chế độ xem có thể được biên dịch trước (http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html).

Giải pháp được chia thành các dự án Khung cơ sở và các dự án tùy chỉnh (mỗi danh mục bao gồm các mô hình và mẫu kho lưu trữ của riêng nó). Các dự án khung được đóng gói trong gói Nuget và sau đó được cài đặt trong bất kỳ dự án tùy chỉnh nào cho phép chức năng phổ biến của bất kỳ dự án nào như quản lý người dùng, vai trò và quyền, quản lý nội dung, vv (thường được gọi là Boiler Plate) bất kỳ dự án mới nào. Điều này cho phép bất kỳ cải tiến nào của bản mẫu được di trú trong bất kỳ dự án tùy chỉnh hiện có nào.

Tuỳ chỉnh cơ sở dữ liệu Initializer:

public class MyMigrateDatabaseToLatestVersion : IDatabaseInitializer<Context> 
{ 
    public void InitializeDatabase(Context context) 
    { 
     //create the base migrator 
     var baseConfig = new FrameworkConfiguration(); 
     var migratorBase = new DbMigrator(baseConfig); 
     //create the custom migrator 
     var customConfig = new Configuration(); 
     var migratorCustom = new DbMigrator(customConfig); 

     //now I need to check what migrations have not yet been applied 
     //and then run them in the correct order 
     if (migratorBase.GetPendingMigrations().Count() > 0) 
     { 
      try 
      { 
       migratorBase.Update(); 
      } 
      catch (System.Data.Entity.Migrations.Infrastructure.AutomaticMigrationsDisabledException) 
      { 
       //if an error occured, the seed would not have run, so we run it again. 
       baseConfig.RunSeed(context); 
      } 
     } 
     if (migratorCustom.GetPendingMigrations().Count() > 0) 
     { 
      try 
      { 
       migratorCustom.Update(); 
      } 
      catch (System.Data.Entity.Migrations.Infrastructure.AutomaticMigrationsDisabledException) 
      { 
       //if an error occured, the seed would not have run, so we run it again. 
       customConfig.RunSeed(context); 
      } 
     } 
    } 
} 

Khung của DB Migrations Cấu hình:

public class FrameworkConfiguration: DbMigrationsConfiguration<Repository.ContextBase> 
{ 
    public Configuration() 
    { 
     AutomaticMigrationsEnabled = false; 
    } 

    public void RunSeed(Repository.ContextBase context) 
    { 
     Seed(context); 
    } 

    protected override void Seed(Repository.ContextBase context) 
    { 
     // This method will be called at every app start so it should use the AddOrUpdate method rather than just Add. 

     FrameworkDatabaseSeed.Seed(context); 
    } 
} 

DB Migrations Cấu hình của dự án tùy chỉnh:

public class Configuration : DbMigrationsConfiguration<Repository.Context> 
{ 
    public Configuration() 
    { 
     AutomaticMigrationsEnabled = false; 
    } 

    public void RunSeed(Repository.Context context) 
    { 
     Seed(context); 
    } 

    protected override void Seed(Repository.Context context) 
    { 
     // This method will be called at every app start so it should use the AddOrUpdate method rather than just Add. 

     CustomDatabaseSeed.Seed(context); 
    } 
} 

Tục DbContext

//nothing special here, simply inherit ContextBase, IContext interface is purely for DI 
public class Context : ContextBase, IContext 
{ 
    //Add the custom DBsets, i.e. 
    public DbSet<Chart> Charts { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     //Assign the model configs, i.e. 
     modelBuilder.Configurations.Add(new ChartConfiguration()); 
    } 
} 

Khung DbContext:

//again nothing special 
public class ContextBase: DbContext 
{ 
    //example DbSet's 
    public virtual DbSet<Models.User> Users { get; set; } 
    protected override void OnModelCreating(DbModelBuilder modelBuilder); 
} 

Trong AppStart global.asax:

 //first remove the base context initialiser 
     Database.SetInitializer<ContextBase>(null); 
     //set the inherited context initializer 
     Database.SetInitializer(new MyMigrateDatabaseToLatestVersion()); 

Trong web.config:

<connectionStrings> 
    <!--put the exact same connection string twice here and name it the same as the base and overridden context. That way they point to the same database. --> 
    <add name="Context" connectionString="Data Source=.\SQLEXPRESS; Initial Catalog=CMS2013; Integrated Security=SSPI;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient"/> 
    <add name="ContextBase" connectionString="Data Source=.\SQLEXPRESS; Initial Catalog=CMS2013; Integrated Security=SSPI;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient"/> 
</connectionStrings> 
+0

Thử đặt chuỗi kết nối trong lớp cơ sở (hoặc chuyển nó từ cha mẹ) tức là công khai ContextBase(): base ("MyConnection") –

+1

Bạn cũng đang gọi cơ sở từ ContextBase? Điều gì sẽ xảy ra nếu bạn thêm nhiều cấu hình hơn, nó có tạo cơ sở dữ liệu cho mọi cấu hình không? Thử thêm cấu hình, sau đó gọi base.OnModelCreating. – MrFox

+1

Bạn có bao giờ tạo ngữ cảnh 'ContextBase' trực tiếp không? ('new ContextBase()') Nếu bạn làm thế, và bạn không muốn, bạn có thể tạo 'ContextBase'' abstract' để đảm bảo trình biên dịch cờ cố gắng làm như vậy. – hvd

Trả lời

5

(từ bình luận)

Bạn đang tạo ContextBase đối tượng trực tiếp, rõ ràng như new T() trong một phương pháp chung với ContextBase như một đối số kiểu chung chung, vì vậy bất kỳ initialisers cho ContextBase cũng chạy. Để ngăn chặn việc tạo các đối tượng ContextBase (nếu nó không bao giờ được khởi tạo trực tiếp, nếu ngữ cảnh bắt nguồn phải luôn được sử dụng), bạn có thể đánh dấu lớp là abstract.

3

ContextBase của bạn dường như có một initializer cũng .. Bạn có thể xóa điều này bằng cách

Database.SetInitializer<ContextBase>(null); 
+0

Cảm ơn bạn, tôi đã tìm thấy giải pháp theo nhận xét của @ hvd ở trên, nhưng câu trả lời này thực sự đã giúp tôi. +1 – hofnarwillie

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