54

我在一个单独的数据访问层类库项目中有一个 MyDbContext。我有一个带有默认 IdentityDbContext 的 ASP.NET MVC 5 项目。这两个上下文使用相同的数据库,我想使用 AspNetUsers 表作为我的一些表的外键。所以我想合并这两个上下文,我也想使用 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");
             }
         }
     }

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

附加信息:在模型生成过程中检测到一个或多个验证错误:

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

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

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

并将 ef cf 模型迁移到 db,以使用 asp.net 身份的命名约定重命名我的表。它现在正在工作!

4

8 回答 8

33
  1. ApplicationUser定义移至您的 DAL。
  2. 继承你的MyDbContextfromIdentityDbContext<ApplicationUser>IdentityDbContext
  3. OnModelCreating - 提供外键信息。
  4. MyDbContext在创建时通过UserManager<ApplicationUser>
于 2013-11-04T10:36:52.157 回答
6

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

IdentityUserLogin: : EntityType 'IdentityUserLogin' 没有定义键。定义此 EntityType 的键。Context.IdentityUserRole: : EntityType 'IdentityUserRole' 没有定义键。定义此 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());

    }

现在应该可以在创建模型时消除错误方法。它对我有用。

于 2014-01-03T21:02:40.877 回答
5

值得注意的是,如果您合并 DBContext,您将身份验证方法(在本例中为 ASP 的身份)绑定到数据访问实现 (EF)。从代码设计的角度来看,这可能被视为混合了您的关注点并违反了单一职责原则

在大多数情况下这可能没问题,但是如果您想在其他非 Web 应用程序(例如桌面或服务器应用程序)中重用您的数据层,这将出现问题,因为 IdentityDbContext 存在于Microsoft.AspNet.Identity.EntityFramework命名空间和您的桌面或服务器应用程序不太可能使用 AspNet Identity 作为其身份验证机制。

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

于 2019-01-24T08:45:11.883 回答
4

这可能是一个旧线程,但这篇文章对于演示如何解决上述问题非常有帮助:http: //blogs.msdn.com/b/webdev/archive/2014/03/20/test-宣布-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 的附加外键。

于 2015-05-09T20:43:37.307 回答
1

1)从 IdentityDbContext 继承上下文后,与身份表(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);
         //....
    }
于 2014-06-17T09:30:48.963 回答
0

我在这里给出了这个问题的完整答案。这是简短的答案:

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

第一个选项:
创建一个继承自 IdentityDbContext 并有权访问类的 DbContext。

   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 源代码中实现我们定制的“OnModelCreating(ModelBuilder builder)”版本

于 2017-01-02T08:12:08.473 回答
0

问题是因为您覆盖了在 IdentityUser 类中实现的方法“OnModelCreating”的内容。

您需要首先从基类调用 OnModelCreating 方法,然后添加您的代码。所以你的方法 OnModelCreating 应该是这样的:

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

     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
于 2018-09-11T14:03:56.033 回答
-2

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

希望有帮助

于 2015-10-03T16:41:20.107 回答