我在单独的Data Accass Layer类库项目中有一个MyDbContext。我有一个 ASP.NET MVC 5项目,带有默认的IdentityDbContext。这两个上下文使用相同的数据库,我想对我的某些表使用 AspNetUsers 表到外键。所以我想合并两个上下文,我也想使用 ASP.NET 身份。
我该怎么做?
请指教,
这是我合并后的上下文:
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>();
}
}
这是我的存储库基类:
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'
的异常,但未在用户代码中处理。
- 将
ApplicationUser
定义移动到 DAL。 - 继承
IdentityDbContext<ApplicationUser>
或IdentityDbContext
的MyDbContext
- OnModelCreation - 提供外键信息。
- 创建
UserManager<ApplicationUser>
时传递MyDbContext
如果您按照上述步骤操作,但无法确定如何提供关键信息,则可能会收到以下消息。 您可能会收到的错误是:
IdentityUserLogin:: EntityType 'IdentityUserLogin' 没有定义键。定义此实体类型的键。Context.IdentityUserRole: : EntityType 'IdentityUserRole' 未定义键。定义此实体类型的键。
创建以下两个类
public class IdentityUserLoginConfiguration : EntityTypeConfiguration<IdentityUserLogin>
{
public IdentityUserLoginConfiguration()
{
HasKey(iul => iul.UserId);
}
}
public class IdentityUserRoleConfiguration : EntityTypeConfiguration<IdentityUserRole>
{
public IdentityUserRoleConfiguration()
{
HasKey(iur => iur.RoleId);
}
}
在应用程序 DbContext 中的 OnModelCreate 方法中,将上面概述的两个配置添加到模型中:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new IdentityUserLoginConfiguration());
modelBuilder.Configurations.Add(new IdentityUserRoleConfiguration());
}
现在,这应该在创建模型时摆脱错误方法。 它为我做到了。
值得注意的是,如果合并 DBContext,则会将身份验证方法(在本例中为 ASP 的标识)绑定到数据访问实现 (EF)。从代码设计的角度来看,这可能被视为混合了您的顾虑并违反了单一责任原则。
在大多数情况下,这可能没问题,但是如果您想在其他非Web应用程序(例如桌面或服务器应用程序)中重用数据层,这将带来问题,因为IdentityDbContext位于Microsoft.AspNet.Identity.EntityFramework命名空间中,并且您的桌面或服务器应用程序不太可能使用AspNet Identity作为其身份验证机制。
我们处于这种情况,最终保留了ASP的第二个数据库上下文,它保留在Web项目中。 然后,当用户登录时,我们将有关用户的一些数据(名字、姓氏等)交叉加载到 Identity 的声明对象中。
这可能是一个古老的线程,但本文在演示如何使上述问题的解决方案工作方面非常有帮助: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);
//....
}
因为没有它,我会得到以下错误:
实体类型"IdentityUserRole"未定义键。定义此实体类型的键。 实体类型"IdentityUserLogin"未定义密钥。定义此实体类型的键。 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 的附加外键。
1)从IdentityDbContext继承上下文后,与身份表上的主键(AspNetUsers等)相关的错误应该消失。
2) IdentityUser 的应用程序用户扩展缺少由实体框架解释为外键的导航属性(这些属性对于从代码导航也非常有用)。
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)我在很多地方读到,在覆盖OnModelCreateating时,你必须调用基方法。似乎有时你可以没有它。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//....
}
我在这里给出了这个问题的完整答案。以下是简短的答案:
基于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 源代码中实现我们的自定义版本的"OnModelCreateating(ModelBuilder builder)"。
导致此问题是因为您覆盖了在 IdentityUser 类中实现的方法"OnModelCreateating"的内容。
您需要首先从基类调用 OnModelCreate 方法,然后添加代码。因此,您的方法OnModelCreate应如下所示:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
我不得不删除这个命名约定:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
并将 ef cf 模型迁移到 db,以使用 asp.net 标识的命名约定重命名我的表。它现在正在工作!
<小时 />这个答案是作为对问题Merge MyDbContext与IdentityDbContext的编辑发布的,由OP martonx在CC BY-SA 3.0下发布。
我尝试了一个简单的方法..从数据库中复制连接字符串并替换DefaultConnection的连接字符串。继续创建用户,所有必要的表都会自动创建到您的数据库中。
希望有帮助