У меня есть MyDbContext в отдельном проекте библиотеки классов Data Accass Layer. И у меня есть проект ASP.NET MVC 5 со стандартным IdentityDbContext. Эти два контекста используют одну и ту же базу данных, и я хочу использовать таблицу 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 identity. Теперь все работает!
ApplicationUser
в свой DAL.MyDbContext
от IdentityDbContext<ApplicationUser>
или IdentityDbContext
.MyDbContext
при создании UserManager<ApplicationUser>
.Вы можете получить следующее сообщение, если вы выполнили описанные выше действия, но не можете понять, как ввести ключевую информацию. Вы можете получить следующую ошибку:
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);
}
}
В методе OnModelCreating в DbContext вашего приложения добавьте две конфигурации, описанные выше, к модели:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new IdentityUserLoginConfiguration());
modelBuilder.Configurations.Add(new IdentityUserRoleConfiguration());
}
Теперь это должно избавить вас от методов ошибок при создании модели. У меня так и получилось.
Это's стоит отметить, что если вы сливаете DBContexts вы не связывая аутентификации подход (АСП'личность в данном случае) для доступа к данным реализации (эф). С точки зрения дизайна кода, которые могут рассматриваться как смешивать ваши проблемы и нарушения единый принцип ответственности.
Что's наверное нормально в большинстве случаев, но если вы хотите использовать ваши данные слоя в другой веб-приложения (например, для настольного компьютера или сервера приложений), это будет представлять проблему, поскольку IdentityDbContext живет в Майкрософт.Паш.Идентичности.И EntityFramework пространства имен и вашего рабочего стола или приложения сервера вряд ли будут используя удостоверение Паш, как их механизм проверки подлинности.
Мы были в этой ситуации и в итоге учета АСП's во-вторых контексте БД, который остался в веб-проекте. Затем мы загружены некоторые данные о пользователе (имя, фамилия и т. д.) на личности'в удовлетворении исковых требований объекта, когда пользователь вошел в систему.
Это может быть старая нить, но эта статья была очень полезна в демонстрации того, как получить решение рабочего вопроса: 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.
После наследования контекста от IdentityDbContext
В вашем расширении ApplicationUser над IdentityUser отсутствуют навигационные свойства, которые интерпретируются Entity Framework как внешние ключи (они также очень полезны для навигации из вашего кода).
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)
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//....
}
Я дал полный ответ на этот вопрос здесь. Вот краткий ответ:
На основе 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 и реализации кастомизированной версии "в OnModelCreating(в modelbuilder Строитель)" из IdentityDbContext исходный текст
Проблема была вызвана тем, что ты переписал содержание метод "в OnModelCreating и", который реализуется в классе IdentityUser.
Вам нужно вызвать метод OnModelCreating от базового класса первым, а после этого добавьте свой код. Так что ваш метод OnModelCreating должен выглядеть так:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
Я попробовал простой способ.. скопируйте строку подключения из вашей БД и заменить строку подключения класс defaultconnection. Идти вперед и создавать пользователей, все необходимые таблицы будут созданы автоматически в базе данных.
Надеюсь, что помогает