Страницы

Поиск по вопросам

пятница, 27 декабря 2019 г.

Переместить таблицы в другую бд с использованием EF Code First

#c_sharp #aspnet_mvc #entity_framework


Есть две базы данных интернет-магазина: Одна основная (контекст наследуется от DbContext),
другая содержит пользователей (ApplicationDbContext, наследуется от IdentityDbContext).
На обеих настроены миграции, которые произвожу раздельно (по этому гайду).

Сегодня столкнулся с необходимостью объединить их в одну БД (хостинг ограничивает
количество баз), в связи с чем появился вопрос: Как переместить все, например, в основную
базу правильно, не нарушив "гомеостаз" EF Code First Migrations и Asp.Net Identity?
Получится ли объединить контексты, учитывая, что они наследуются от разных классов?
Что делать дальше? Или все обстоит намного проще (например 2 контекста в одной БД)?
Прошу пошагово расписать если не действия, то хотя бы логику процесса, который мне
необходимо проделать для решения проблемы.

P.S.: Магазин только пишется, пользователь всего 1, так что пересоздание таблицы
с пользователями не страшно. Лишь бы на выходе все работало.

UPD:

Прикрепляю класс основного контекста по просьбе @Bald:

public class ProductContext : DbContext
    {
        public DbSet Products { get; set; }
        public DbSet Categories { get; set; }
        public DbSet ProductTypes { get; set; }
        public DbSet TopNotes { get; set; }
        public DbSet HeartNotes { get; set; }
        public DbSet BaseNotes { get; set; }
        public DbSet Features { get; set; }
        public DbSet ProductValues { get; set; }
        public DbSet Variations { get; set; }
        public DbSet Visitors { get; set; }
        public DbSet Carts { get; set; }
        public DbSet Orders { get; set; }
        public DbSet OrderDetails { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
        modelBuilder.Entity().HasMany(c => c.ProductTypes)
            .WithMany(s => s.Products)
            .Map(t => t.MapLeftKey("ProductId")
            .MapRightKey("ProductTypeId")
            .ToTable("Product_ProductTypes"));

        modelBuilder.Entity().HasMany(c => c.TopNotes)
            .WithMany(s => s.Products)
            .Map(t => t.MapLeftKey("ProductId")
            .MapRightKey("TopNoteId")
            .ToTable("Product_TopNotes"));

        modelBuilder.Entity().HasMany(c => c.HeartNotes)
            .WithMany(s => s.Products)
            .Map(t => t.MapLeftKey("ProductId")
            .MapRightKey("HeartNoteId")
            .ToTable("Product_HeartNotes"));

        modelBuilder.Entity().HasMany(c => c.BaseNotes)
            .WithMany(s => s.Products)
            .Map(t => t.MapLeftKey("ProductId")
            .MapRightKey("BaseNoteId")
            .ToTable("Product_BaseNotes"));

        modelBuilder.Entity().HasMany(c => c.ProductValues)
        .WithMany(s => s.Products)
        .Map(t => t.MapLeftKey("ProductId")
        .MapRightKey("ProductValueId")
        .ToTable("Product_ProductValues"));
        }
    }


и класс ApplicationDbContext, на всякий случай:

public class ApplicationDbContext : IdentityDbContext
    {
        public ApplicationDbContext()
            : base("ApplicationDbContext", throwIfV1Schema: false)
        {
        }

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

    


Ответы

Ответ 1



Решил задачу переносом основного контекста в ApplicationDbContext (спасибо @Bald). После такого объединения контекстов, при попытке провести Code First Migrations консоль выдала ошибку: "One or more validation errors were detected during model generation: Ciel2.Models.IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined. Define the key for this EntityType. Ciel2.Models.IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType. IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type 'IdentityUserRole' that has no keys defined. IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type 'IdentityUserLogin' that has no keys defined." После нескольких дней поисков, нашел ответ тут: https://stackoverflow.com/questions/19994590/asp-net-identity-validation-error. Суть проблемы вкратце (а также решение): Наличие в контексте данных сущностей, связанных отношением многие-ко-многим, вынуждает к переопределению метода OnModelCreating (что отражено в моем коде). Таким образом для корректной работы объединенных контекстов необходимо приписать: base.OnModelCreating(modelBuilder); непосредственно перед основным содержанием метода. После этих изменений миграция заработала и никаких проблем с Entity Framework больше не возникает. Полностью мой окончательный контекст данных выглядит так (не обращайте внимание на разницу в сущностях, за время работы он немного вырос): public class ApplicationUser : IdentityUser { public string FirstName { get; set; } public ICollection
Addresses { get; set; } public string AvatarUrl { get; set; } public ApplicationUser() { Addresses = new List
(); } public async Task GenerateUserIdentityAsync(UserManager manager) { var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); return userIdentity; } } public class ApplicationDbContext : IdentityDbContext { public DbSet Products { get; set; } public DbSet Categories { get; set; } public DbSet ProductTypes { get; set; } public DbSet TopNotes { get; set; } public DbSet HeartNotes { get; set; } public DbSet BaseNotes { get; set; } public DbSet Features { get; set; } public DbSet ProductValues { get; set; } public DbSet Variations { get; set; } public DbSet Visitors { get; set; } public DbSet Carts { get; set; } public DbSet Favs { get; set; } public DbSet Orders { get; set; } public DbSet OrderDetails { get; set; } public DbSet
Addresses { get; set; } public DbSet OrderStatuses { get; set; } public DbSet Pictures { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // та самая строка кода modelBuilder.Entity().HasMany(c => c.ProductTypes) .WithMany(s => s.Products) .Map(t => t.MapLeftKey("ProductId") .MapRightKey("ProductTypeId") .ToTable("Product_ProductTypes")); modelBuilder.Entity().HasMany(c => c.TopNotes) .WithMany(s => s.Products) .Map(t => t.MapLeftKey("ProductId") .MapRightKey("TopNoteId") .ToTable("Product_TopNotes")); modelBuilder.Entity().HasMany(c => c.HeartNotes) .WithMany(s => s.Products) .Map(t => t.MapLeftKey("ProductId") .MapRightKey("HeartNoteId") .ToTable("Product_HeartNotes")); modelBuilder.Entity().HasMany(c => c.BaseNotes) .WithMany(s => s.Products) .Map(t => t.MapLeftKey("ProductId") .MapRightKey("BaseNoteId") .ToTable("Product_BaseNotes")); modelBuilder.Entity().HasMany(c => c.ProductValues) .WithMany(s => s.Products) .Map(t => t.MapLeftKey("ProductId") .MapRightKey("ProductValueId") .ToTable("Product_ProductValues")); } public ApplicationDbContext() : base("ApplicationDbContext", throwIfV1Schema: false) { } public static ApplicationDbContext Create() { return new ApplicationDbContext(); } } Еще раз большое спасибо пользователю @Bald и сайту StackOverflow за помощь в решении задачи.

Комментариев нет:

Отправить комментарий