2016-09-04 2 views
2

Я пытаюсь добиться разделения слоев с проектом, над которым я работаю. Идея состоит в том, что я могу использовать любую функцию, которую веб-сайт имеет и модулировать. Например, если вы возьмете что-то вроде новостей и хотите добавить эту функцию на сайт, то в коде вам просто нужно будет импортировать службу новостей, модели, слой данных и т. Д. Все импортируются вместе с ним.Расширение DbContext из другого проекта

Обратите внимание, что я использую Ninject как часть проекта для впрыскивания зависимостей, поэтому мне не нужно ссылаться на конкретные классы, я только ссылаюсь на контракты.

У меня есть основной проект и слой данных, как например:

public class MainDbContext : CustomIdentityDbContext, IMainDbContext 
{ 

} 

Как вы можете видеть, что расширяет CustomIdentityDbContext, которое выглядит следующим образом:

public class CustomIdentityDbContext : IdentityDbContext<CustomUser>, ICustomIdentityDbContext 
{ 
    public CustomIdentityDbContext() 
     : base("DefaultConnection", throwIfV1Schema: false) 
    { 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 
     modelBuilder.Entity<IdentityUserClaim>().ToTable("UserClaim"); 
     modelBuilder.Entity<IdentityUserRole>().ToTable("UserRole"); 
     modelBuilder.Entity<IdentityUserLogin>().ToTable("UserLogin"); 
     modelBuilder.Entity<IdentityRole>().ToTable("Role"); 
     modelBuilder.Entity<AzularisUser>().ToTable("User"); 
     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
     modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 
    } 

    public static DbContext Create() 
    { 
     return new CustomIdentityDbContext(); 
    } 
} 

Моя проблема заключается в том, что мне нужно иметь таблицу новостей, а затем мне нужен EF6 для сопоставления этой таблицы, как и для Identity. Я не могу понять, как создать эти отношения. Как добавить DbSet<News> News { get; set; } в мой MainDbContext без необходимости писать эту строку там и ссылаться на объект новостей. Поэтому я пытаюсь добиться его динамического добавления в мой класс MainDbContext в тот момент, когда я ссылаюсь на свою службу, поскольку эта служба будет запускать все остальные классы в создание себя через ninject и привязку.

Другими словами, слой данных для новостей необходимо внедрить в MainDbContext без MainDbContext, зная об этом в своих ссылках. Что-то вроде этого возможно? Если да, то как мне это достичь?

Вот что я пробовал:

public class NewsDbContext : DbContext, INewsDbContext 
{ 
    public DbSet<News> News { get; set; } 
    public NewsDbContext() : base("DefaultConnection") { } 

    public IEnumerable<INews> QueryNews() 
    { 
     return News; 
    } 
} 

Приведенный выше код компилируется и работает, однако, он не создает таблицу и когда я пытаюсь запросить его или вставить запись, она будет ломаться в виде таблицы не существует. Я не совсем уверен, как это сделать, и у меня много идей. Что-то вроде этого возможно?

EDIT:

я понял, что не может быть объяснено себя должным образом. Дай мне попробовать снова. У меня многослойная структура. У меня есть данные о службах, данных, доменах и DTO. Эти 4 слоя составляют плагин. Вдобавок к этим 4 слоям, у меня есть еще 4, которые являются интерфейсами этих слоев, так что, другими словами, контракты. Я использую Ninject для привязки моих контрактов к уровням реализации, так что основной проект никогда не ссылается на уровни реализации в проекте. По этой причине я пытаюсь подключить слой данных к слою данных основного проекта, без основного слоя данных проекта, фактически ссылающегося на слой данных плагина. Проблема в том, что плагин будет иметь свои собственные таблицы. Я бы хотел, чтобы эти таблицы автоматически создавались с EF6 при первом запуске проекта.

Мой главный проект также разделен так же, как плагин, он имеет все 4 слоя плюс уровень менеджера. Менеджер представляет собой набор сервисов и не служит никакой другой цели, он просто создает их на основе контракта с помощью Ninject. Ядро проекта содержит все представления, скрипты и файлы css, но он ссылается на интерфейс менеджера. С ninject я создаю экземпляр менеджера. Менеджер снова имеет все ссылки на контракты, а с помощью ninject он создает экземпляры этих контрактов. Службы, ссылающиеся на контракты уровня данных и уровня данных, будут запрашивать информацию и возвращать результаты службе, которая будет передана обратно контроллеру. Надеюсь, это объясняет мою структуру немного лучше.При таком подходе я пытаюсь создать trully модульный проект, где вы можете поменять местами реализацию dll и продолжить работу над проектом, не перекомпилировать всю черную вещь. Я могу иметь две полностью раздельные функции на 2 dll, но пока они реализуют один и тот же контракт, веб-сайт должен работать независимо от того, какая у него dll в своей папке.

Все, что я только что описал, работает, за исключением того, что оно работает с EF6. У меня очень похожая структура с DAPPER, и там все это хорошо и денди, когда вы пишете свой собственный запрос, и поэтому у меня не было проблем. Я пытаюсь воспроизвести это с помощью EF6. Итак, еще раз, мой вопрос: как мне получить EF6 для создания таблиц, как добавить их динамически, когда единственное, на что ссылается, - это интерфейс службы. Может быть, интерфейс может иметь функцию MapTables, но опять же я не уверен, как выполнить динамическое добавление к EF6.

Идея, которая у меня была, и я не уверен, что это может работать, и как я это сделаю, но что, если я передаю контекст БД как тип, а не расширяю его?

+0

Обычно нужно, чтобы 'NewsDbContext' был подклассом' CustomIdentityDbContext'. Но если я правильно вас понимаю, вы хотите, чтобы сборка, содержащая «Новости», была независимой от «базовой» сборки. Другими словами, веб-приложение должно иметь возможность импортировать базовую сборку и любую другую сборку, и они должны каким-то образом быть объединены в один слой данных. Это верно? –

+0

@GertArnold Да, я надеюсь объединить их в один слой данных. Веб-приложение должно иметь возможность импортировать сборку новостей и использовать ее через службу. – Bojan

+0

Большой вопрос: * who * (какая сборка) знает, какие классы должны быть частью модели класса Entity Framework? –

ответ

1

Я частично разрешил свою проблему. Я отправлю это как ответ и обновление после того, как у меня будет полное решение. До сих пор я узнал, как получить мои таблицы. Именно с помощью следующего кода внутри DB контексте основного проекта:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    var entityMethod = typeof(DbModelBuilder).GetMethod("Entity"); 

    foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) 
    { 
     var entityTypes = assembly 
      .GetTypes() 
      .Where(t => 
      t.GetCustomAttributes(typeof(PersistentAttribute), inherit: true) 
      .Any()); 

     foreach (var type in entityTypes) 
     { 
      entityMethod.MakeGenericMethod(type) 
       .Invoke(modelBuilder, new object[] { }); 
     } 
    } 

    base.OnModelCreating(modelBuilder); 
} 

Приведенный выше код будет гарантировать, что таблицы созданы для любого класса, который имеет «PersistentAttribute» добавил. Моя следующая проблема заключается в попытке запроса из внешней DLL. Таким образом, уровень данных в новостном проекте должен иметь возможность запрашивать себя, передав каким-то образом контекст, созданный в основном проекте. У меня мало идей по этому поводу, благодаря ninject, я опубликую больше, как только выясню.

Смежные вопросы