2014-11-25 4 views
0

Как правильно установить отношения «один-к-одному» в коде Entity Framework с использованием API?Настройка отношения «один-к-одному»

Корневая модель - это класс Project. Каждый проект содержит ровно одно предложение. Он также может также содержать один заказ клиента.

Цель исторических моделей содержат снимки соответствующих неисторических строк (когда Project добавляется новый Project создаются и чем скопированный на новый ProjectHistorical класс, если он редактируется, новый ProjectHistorical класс создается с данными отредактированного Project). Исторические объекты должны быть AutoMapper дружественными. Вы можете рассматривать исторические модели как глупое, тривиальное и наивное обходное решение для отсутствия поддержки временных баз данных в движке базы данных.

При такой конфигурации, я испытываю следующие трудности:

  1. CustomerOrders и Offers таблицы и их исторические аналогов имеет Project_Id колонка генерируется. Я не нашел способ как принудительно использовать первичный ключ Id или прокомментировал ProjectId свойства (Я предпочитаю использовать прокомментированные ProjectId свойства).
  2. ProjectHistoricals стол имеет CustomerOrder_Id и Offer_Id составленные столбцы. Я не нашел способ как заставить использование Id колонок (обратите внимание, что Id столбца не является первичным ключом на исторических таблицах) или комментируемые CustomerOrderId и OfferId колонны (на обоих Project и ProjectHistorical классов; Я предпочитаю использовать прокомментированные столбцы CustomerOrderId и OfferId).

Я попытался много искать и пробовал еще больше вещей, но ничего не работало (ожидалось).

У меня есть следующие модели:

public class Project 
{ 
    public virtual int Id { get; set; } 
    // public virtual int OfferId { get; set; } 
    public virtual Offer Offer { get; set; } 
    // public virtual int? CustomerOrderId { get; set; } 
    public virtual CustomerOrder CustomerOrder { get; set; } 
} 

public class ProjectHistorical 
{ 
    public virtual int LogId { get; set; } 
    public virtual int Id { get; set; } 
    // public virtual int OfferId { get; set; } 
    public virtual Offer Offer { get; set; } 
    // public virtual int? CustomerOrderId { get; set; } 
    public virtual CustomerOrder CustomerOrder { get; set; } 
} 

public class CustomerOrder 
{ 
    public virtual int Id { get; set; } 
    // public virtual int ProjectId { get; set; } 
    public virtual Project Project { get; set; } 
} 

public class CustomerOrderHistorical 
{ 
    public virtual int LogId { get; set; } 
    public virtual int Id { get; set; } 
    // public virtual int ProjectId { get; set; } 
    public virtual Project Project { get; set; } 
} 

public class Offer 
{ 
    public virtual int Id { get; set; } 
    // public virtual int ProjectId { get; set; } 
    public virtual Project Project { get; set; } 
} 

public class OfferHistorical 
{ 
    public virtual int LogId { get; set; } 
    public virtual int Id { get; set; } 
    // public virtual int ProjectId { get; set; } 
    public virtual Project Project { get; set; } 
} 

А следующий свободно апи (первичный ключ должен быть всегда называется Id как все модели реализует общий интерфейс, чем потребляется родовыми частями приложения):

modelBuilder.Conventions.Remove<IdKeyDiscoveryConvention>(); 
modelBuilder.Conventions.Remove<ForeignKeyAssociationMultiplicityConvention>(); 
modelBuilder.Conventions.Remove<PrimaryKeyNameForeignKeyDiscoveryConvention>(); 
modelBuilder.Conventions.Remove<OneToOneConstraintIntroductionConvention>(); 
modelBuilder.Conventions.Remove<TypeNameForeignKeyDiscoveryConvention>(); 
modelBuilder.Conventions.Remove<AssociationInverseDiscoveryConvention>(); 
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); 
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 

modelBuilder.Entity<CustomerOrder>().HasKey(t => t.Id); 

modelBuilder.Entity<CustomerOrderHistorical>().HasKey(t => t.LogId); 
modelBuilder.Entity<CustomerOrderHistorical>().HasRequired(t => t.Project); 

modelBuilder.Entity<Offer>().HasKey(t => t.Id); 

modelBuilder.Entity<OfferHistorical>().HasKey(t => t.LogId); 
modelBuilder.Entity<OfferHistorical>().HasRequired(t => t.Project); 

modelBuilder.Entity<Project>().HasKey(t => t.Id); 
modelBuilder.Entity<Project>().HasRequired(t => t.Offer).WithRequiredPrincipal(t => t.Project); 
modelBuilder.Entity<Project>().HasOptional(t => t.CustomerOrder).WithRequired(t => t.Project); 

modelBuilder.Entity<ProjectHistorical>().HasKey(t => t.LogId); 
modelBuilder.Entity<ProjectHistorical>().HasRequired(t => t.Offer); 
modelBuilder.Entity<ProjectHistorical>().HasOptional(t => t.CustomerOrder); 

Это как модель составлена ​​в базе данных по Entity Framework:

 CreateTable(
      "dbo.CustomerOrderHistoricals", 
      c => new 
       { 
        LogId = c.Int(nullable: false, identity: true), 
        Id = c.Int(nullable: false), 
        Project_Id = c.Int(nullable: false), 
       }) 
      .PrimaryKey(t => t.LogId) 
      .ForeignKey("dbo.Projects", t => t.Project_Id) 
      .Index(t => t.Project_Id); 

     CreateTable(
      "dbo.Projects", 
      c => new 
       { 
        Id = c.Int(nullable: false, identity: true), 
       }) 
      .PrimaryKey(t => t.Id); 

     CreateTable(
      "dbo.CustomerOrders", 
      c => new 
       { 
        Id = c.Int(nullable: false, identity: true), 
        Project_Id = c.Int(nullable: false), 
       }) 
      .PrimaryKey(t => t.Id) 
      .ForeignKey("dbo.Projects", t => t.Project_Id) 
      .Index(t => t.Project_Id); 

     CreateTable(
      "dbo.Offers", 
      c => new 
       { 
        Id = c.Int(nullable: false, identity: true), 
        Project_Id = c.Int(nullable: false), 
       }) 
      .PrimaryKey(t => t.Id) 
      .ForeignKey("dbo.Projects", t => t.Project_Id) 
      .Index(t => t.Project_Id); 

     CreateTable(
      "dbo.OfferHistoricals", 
      c => new 
       { 
        LogId = c.Int(nullable: false, identity: true), 
        Id = c.Int(nullable: false), 
        Project_Id = c.Int(nullable: false), 
       }) 
      .PrimaryKey(t => t.LogId) 
      .ForeignKey("dbo.Projects", t => t.Project_Id) 
      .Index(t => t.Project_Id); 

     CreateTable(
      "dbo.ProjectHistoricals", 
      c => new 
       { 
        LogId = c.Int(nullable: false, identity: true), 
        Id = c.Int(nullable: false), 
        CustomerOrder_Id = c.Int(), 
        Offer_Id = c.Int(nullable: false), 
       }) 
      .PrimaryKey(t => t.LogId) 
      .ForeignKey("dbo.CustomerOrders", t => t.CustomerOrder_Id) 
      .ForeignKey("dbo.Offers", t => t.Offer_Id) 
      .Index(t => t.CustomerOrder_Id) 
      .Index(t => t.Offer_Id); 
+1

: Ваш личный кабинет? Отношения один к одному обычно подразумевают, что две таблицы должны быть объединены в одну таблицу. –

+0

Я знаю, что это должно быть то же самое с точки зрения теории. Однако, с точки зрения бизнеса, Project, Offer и CustomerOrder - это отличная вещь. Вы можете себе представить, что проект представляет собой папку, содержащую несколько документов.Другое воображение состоит в том, что проект является рабочим процессом, а существование других моделей говорит о том, на каком этапе вы находитесь в процессе (во-первых, вы создаете предложение для клиента, чем получаете заказ от клиента, а затем вы ...) , – alik

ответ

0

Вы можете прочитать this tutorial или проверить this answer на stackoverflow или this answer на MSDN.

+0

Спасибо. Я уже видел две связанные статьи, но я проверю второй. PS: Последняя ссылка не является ответом на stackoverflow. – alik

+1

Если я правильно понимаю вторую ссылку, особенно ссылку на статью http://weblogs.asp.net/manavi/associations-in-ef-4-1-code-first -part-5-one-to-one-foreign -key-ассоциации EF (по крайней мере, в версии 4.1) не обоснованно поддерживают отношения «один-к-одному», поэтому мне нужно придерживаться отношений «один ко многим», которые я уже сделал в качестве обходного пути. Или мое понимание не так? В EF5/EF6 ничего не изменилось по этому поводу? PS: Не указано в вопросе. Первичные ключи моей модели должны иметь имя Id в каждом объекте. – alik

+1

Исправить. Придерживайтесь своего обходного пути. Мы также работаем с обходным путем :) –

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