将MyDbContext与IdentityDbContext合并

时间:2013-11-04 08:49:08

标签: asp.net-mvc asp.net-identity

我在一个单独的Data Accass Layer类库项目中有一个MyDbContext。我有一个带有默认IdentityDbContext的ASP.NET MVC 5项目。这两个上下文使用相同的数据库,我想将AspNetUsers表用于我的表的外键。 所以我想合并两个Context,我也想使用ASP.NET Identity。

我该怎么做?

请建议,

这是我合并后的上下文:

public class CrmContext : IdentityDbContext<CrmContext.ApplicationUser> //DbContext
{
    public class ApplicationUser : IdentityUser
    {
        public Int16 Area { get; set; }
        public bool Holiday { get; set; }
        public bool CanBePublic { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    public CrmContext()
        : base("DefaultConnection")
    {

    }

    public DbSet<Case> Case { get; set; }
    public DbSet<CaseLog> CaseLog { get; set; }
    public DbSet<Comment> Comment { get; set; }
    public DbSet<Parameter> Parameter { get; set; }
    public DbSet<Sign> Sign { get; set; }
    public DbSet<Template> Template { get; set; }
    public DbSet<Read> Read { get; set; }

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

这是我的RepositoryBase类:

    public class RepositoryBase<TContext, TEntity> : IRepositoryBaseAsync<TEntity>, IDisposable
        where TContext : IdentityDbContext<CrmContext.ApplicationUser> //DbContext
        where TEntity : class
    {
        private readonly TContext _context;
        private readonly IObjectSet<TEntity> _objectSet;

        protected TContext Context
        {
            get { return _context; }
        }

        public RepositoryBase(TContext context)
        {
            if (context != null)
            {
                _context = context;
                //Here it is the error:
                _objectSet = (_context as IObjectContextAdapter).ObjectContext.CreateObjectSet<TEntity>();
             }
             else
             {
                 throw new NullReferenceException("Context cannot be null");
             }
         }
     }

EntityFramework.dll中出现'System.Data.Entity.ModelConfiguration.ModelValidationException'类型的异常,但未在用户代码中处理

其他信息:在模型生成期间检测到一个或多个验证错误:

更新:我找到了解决方案。

我不得不删除这个命名约定:

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

将ef cf模型迁移到db,使用asp.net标识的命名约定重命名我的表。 它现在正在运作!

8 个答案:

答案 0 :(得分:30)

  1. ApplicationUser定义移至您的DAL。
  2. MyDbContextIdentityDbContext<ApplicationUser>
  3. 继承您的IdentityDbContext
  4. OnModelCreating - 提供外键信息。
  5. 在创建MyDbContext
  6. 时通过UserManager<ApplicationUser>

答案 1 :(得分:6)

如果您按照上述步骤进行操作,但无法确定如何提供关键信息,则可能会收到以下消息。您可能收到的错误是:

IdentityUserLogin :: EntityType&#39; IdentityUserLogin&#39;没有定义键。定义此EntityType的键。 Context.IdentityUserRole :: EntityType&#39; IdentityUserRole&#39;没有定义键。定义此EntityType的密钥。

创建以下两个类

public class IdentityUserLoginConfiguration : EntityTypeConfiguration<IdentityUserLogin>
{

    public IdentityUserLoginConfiguration()
    {
        HasKey(iul => iul.UserId);
    }

}

public class IdentityUserRoleConfiguration : EntityTypeConfiguration<IdentityUserRole>
{

    public IdentityUserRoleConfiguration()
    {
        HasKey(iur => iur.RoleId);
    }

}

在Applications DbContext中的OnModelCreating方法中,将上面列出的两个配置添加到模型中:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Configurations.Add(new IdentityUserLoginConfiguration());
        modelBuilder.Configurations.Add(new IdentityUserRoleConfiguration());

    }

现在应该在创建模型时摆脱错误方法。它确实适合我。

答案 2 :(得分:4)

这可能是一个旧线程,但本文非常有助于演示如何解决上述问题的解决方案: http://blogs.msdn.com/b/webdev/archive/2014/03/20/test-announcing-rtm-of-asp-net-identity-2-0-0.aspx

我最终不得不包括

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

因为没有它,我会收到以下错误:

  

EntityType'IdentityUserRole'没有定义键。定义此EntityType的键。   EntityType'IdentityUserLogin'没有定义键。定义此EntityType的键。   EntitySet'IdentityUserRoles'基于类型'IdentityUserRole',没有定义键。   EntitySet'IdentityUserLogins'基于没有定义键的类型'IdentityUserLogin'。

如果我按上述方法添加这些配置:

public class IdentityUserLoginConfiguration : EntityTypeConfiguration<IdentityUserLogin>
{
    public IdentityUserLoginConfiguration()
    {
        HasKey(iul => iul.UserId);
    }
}

public class IdentityUserRoleConfiguration : EntityTypeConfiguration<IdentityUserRole>
{
    public IdentityUserRoleConfiguration()
    {
        HasKey(iur => iur.RoleId);
    }
}

它会创建一个名为Application_User的附加外键。

答案 3 :(得分:4)

值得注意的是,如果合并DBContext,则将身份验证方法(在这种情况下为ASP的Identity)绑定到数据访问实现(EF)。从代码设计的角度来看,这可能会引起您的担忧和对Single Responsibility Principle的违反。

在大多数情况下这可能很好,但是如果您想在其他非Web应用程序(例如台式机或服务器应用程序)中重用数据层,则会出现问题,因为IdentityDbContext位于{{3} }名称空间以及您的桌面或服务器应用程序不太可能使用AspNet Identity作为其身份验证机制。

我们当时处于这种情况,最终保留了ASP的第二个数据库上下文,该上下文保留在Web项目中。然后,当用户登录时,我们将有关用户的一些数据(名字,姓氏等)交叉加载到Identity的Claims对象中。

答案 4 :(得分:1)

1)从IdentityDbContext继承上下文后,与Identity表(AspNetUsers等)上的主键相关的错误应该消失。

2)IdentityUser的ApplicationUser扩展缺少实体框架解释为外键的导航属性(这些对于从代码导航也非常有用)。

public class ApplicationUser : IdentityUser
{
    public Int16 Area { get; set; }
    public bool Holiday { get; set; }
    public bool CanBePublic { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    //*** Add the following for each table that relates to ApplicationUser (here 1-to-many)
    public virtual IList<Case> Cases { get; set; } //Navigation property
    //*** and inside the case class you should have 
    //*** both a public ApplicationUser ApplicationUser {get;set;}
    //*** and a public string ApplicationUserId {get;set;} (string because they use GUID not int)
}

3)我在许多地方读到,当覆盖OnModelCreating时,你必须调用基本方法。似乎有时你可以没有它。

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

答案 5 :(得分:0)

我已经对这个问题给出了完整的答案here。 这是简短的回答:

基于IdentityDbContext源代码,如果我们想将IdentityDbContext与我们的DbContext合并,我们有两个选择:

第一选项:
创建一个DbContext,它继承自IdentityDbContext并可以访问这些类。

   public class ApplicationDbContext 
    : IdentityDbContext
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }

    static ApplicationDbContext()
    {
        Database.SetInitializer<ApplicationDbContext>(new ApplicationDbInitializer());
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

    // Add additional items here as needed
}

第二个选项: (不推荐)
如果我们自己编写所有代码,我们实际上不必继承IdentityDbContext。
所以基本上我们可以继承DbContext并从IdentityDbContext source code

实现我们的定制版“OnModelCreating(ModelBuilder builder)”

答案 6 :(得分:0)

引起此问题的原因是您重写了IdentityUser类中实现的方法“ OnModelCreating”的内容。

首先需要从基类中调用OnModelCreating方法,然后添加代码。因此,您的OnModelCreating方法应如下所示:

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

     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}

答案 7 :(得分:-2)

我尝试了一种简单的方法..从数据库复制连接字符串并替换DefaultConnection的连接字符串。继续创建用户,所有必要的表都会自动在您的数据库中创建。

希望有所帮助