【问题标题】:.net mvc codefirst multiple SiteDataContextInitializer one database.net mvc 代码先多个 Site DbContext Initializer 一个数据库
【发布时间】:2012-05-13 21:49:05
【问题描述】:

我正在尝试创建要重用的模块。例如,创建和处理用户操作(登录、注册等)、然后构建它并在其他项目中使用 dll 的 Membership 项目。

因此,在 Membership 项目中,我使用自己的命名空间创建我的 POCO 类和 DataContext:

namespace CloudOne.Membership.Models
{
    public class SiteDataContext : DbContext
    {
        public DbSet<User> Users { get; set; }
        public DbSet<UserRole> UserRoles { get; set; }
        public DbSet<UserRoleJoin> UserRoleJoins { get; set; }

        // Twist our database
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            base.OnModelCreating(modelBuilder);
        }
    }

    public class SiteDataContextInitializer : DropCreateDatabaseAlways<SiteDataContext>
    {
        protected override void Seed(SiteDataContext context)
        {
            // users

            var user = new User { UserID = "UserA", Password = "D33177D41FD48F0027BD10D2689E8599", DateCreated=DateTime.Now, DateLastLogin = DateTime.Now };

            context.Users.Add(user);

            var roles = new List<UserRole>
            {
                new UserRole { RoleID = "Admin" },
                new UserRole { RoleID = "Editor" },
                new UserRole { RoleID = "Customer" },
                new UserRole { RoleID = "Guest" }
            };

            roles.ForEach(m => context.UserRoles.Add(m));

            var userRoleJoin = new UserRoleJoin { UserID = "UserA", RoleID = "Admin" };

            context.UserRoleJoins.Add(userRoleJoin);
        }
    }
}

然后我在一个主项目中使用,使用CloudOne.Membership.dll作为参考,主项目又有了自己的Namespace、DataContext和seed:

namespace CloudOne.Models
{
    public class SiteDataContext : DbContext
    {
        public DbSet<Category> Categories { get; set; }
        public DbSet<Product> Products { get; set; }
        public DbSet<ProductPrice> ProductPrices { get; set; }
        public DbSet<ProductPicture> ProductPictures { get; set; }

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

    public class SiteDataContextInitializer : DropCreateDatabaseAlways<SiteDataContext>
    {
        protected override void Seed(SiteDataContext context)
        {
            // data seeding here

            context.SaveChanges();
        }
    }
}

然后我从 global.asax 调用两个初始化器

protected void Application_Start()
        {
            Database.SetInitializer<SiteDataContext>(new SiteDataContextInitializer());
            Database.SetInitializer<CloudOne.Membership.Models.SiteDataContext>(new CloudOne.Membership.Models.SiteDataContextInitializer());

            AreaRegistration.RegisterAllAreas();

            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
        }

现在的问题是,当我访问使用主项目类的页面时,它会为主类中定义的 POCO 创建数据库(ModelFirst),并按照主项目数据上下文中定义的方式播种数据,但它不会创建POCO 或会员资格的种子。而且,当访问使用会员数据的页面时...它仅为会员重新创建数据库。

那么,我怎样才能将成员资格(和其他模块)与主项目一起使用,而不必手动添加表、关系和播种,而不是在主项目中?

例如,主要项目是关于购物车的,为了用户会员模块,我必须复制 ShoppingCart DataContext 中的所有 POCO 类以及创建用户、角色等的种子部分。但该代码已经在里面会员资格。初始化器,那么如何封装它,这样就不需要将所有模块的代码复制到主应用程序中就可以拥有包含所有表和数据的数据库?

【问题讨论】:

    标签: entity-framework ef-code-first poco datacontext


    【解决方案1】:

    这很有可能是一个连接字符串问题,并且数据库实际上是在您期望的地方创建的。

    我的猜测是您在 web.config 中定义了SiteDataContext 连接字符串,但您没有明确定义CloudOne.Membership.Models.SiteDataContext 连接字符串。

    EF 将考虑这两个单独的 DbContexts —— 你不能简单地通过使类同名来合并它们。因此,它正在寻找单独的连接字符串,以配合您分配的单独初始化指令。

    我没有在 EF 4.1 上尝试过这个,但我相信模型更改跟踪将防止两个上下文共享同一个物理数据库 (as described here)。

    简而言之,我认为您的直接问题是您没有使用连接字符串初始化您的成员资格上下文,因此它默认为本地。 EF 将尝试在活动应用程序域(您的购物车网站)中查找具有您的上下文名称的连接字符串,因此它需要位于该站点的 web.config 中。

    【讨论】:

    • 感谢您抽出宝贵时间回答。是的,我同意你的看法,问题是我找不到在解决方案级别为所有连接声明一个字符串的方法,所以现在它在项目级别,正如你所说,在本地是不同的。跨度>
    • 如果您的解决方案是围绕 MVC 或 ASP.NET Web 应用程序,那么您只需在 Web.config 中放置正确的连接字符串。连接字符串的名称很重要——它应该与您的 DbContext 名称匹配,并且可能需要使用命名空间进行限定。如果您的解决方案是控制台或桌面应用程序,则可以使用 App.config 执行相同的操作。如果这回答了您的问题,请将此答案作为您的解决方案。
    猜你喜欢
    • 2018-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-06
    • 2015-01-15
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多