Подтвердить что ты не робот

Entity Framework Code First: настройка взаимной связи "один-на-один" с использованием аннотаций

У меня есть два объекта, которые я пытаюсь связать (один к одному) с использованием ассоциаций внешних ключей.

public class StandardRack {
    public int Id {get;set}
    public StandardRelay StandardRelay {get;set} 
}

public class StandardRelay {
    public int Id {get;set} 

    public int StandardRack_Id {get;set;}
    [Required][ForeignKey("StandardRack_Id")]
    public StandardRack StandardRack { get; set; }
}

Это исключает исключение ModelValidationException. Любые идеи, почему такое, казалось бы, простое взаимно однозначное отношение "один к одному" не могут быть настроены.

Edit:

Вот Исключение:

System.Data.Entity.ModelConfiguration.ModelValidation Исключение было обнаружено       Сообщение = Во время генерации модели были обнаружены одна или несколько ошибок проверки:

System.Data.Edm.EdmAssociationEnd:: множественность недействительна в роли "StandardRelay_StandardRack_Source" в отношении "StandardRelay_StandardRack". Поскольку свойства зависимой роли не являются ключевыми свойствами, верхняя граница множественности зависимой роли должна быть *.

Источник = EntityFramework       Трассировки стека:            в System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateAndSerializeCsdl(модель EdmModel, создатель XmlWriter)            в System.Data.Entity.ModelConfiguration.Edm.EdmModelExtensions.ValidateCsdl(модель EdmModel)            в System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)            в System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)            в System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)            в System.Data.Entity.Internal.RetryLazy 2.GetValue(TInput input) at System.Data.Entity.Internal.LazyInternalContext.InitializeContext() at System.Data.Entity.Internal.InternalContext.Initialize() at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType) at System.Data.Entity.Internal.Linq.InternalSet 1.Initialize()            в System.Data.Entity.Internal.Linq.InternalSet 1.GetEnumerator() at System.Data.Entity.Infrastructure.DbQuery 1.System.Collections.Generic.IEnumerable.GetEnumerator()            в коллекции System.Collections.Generic.List 1..ctor(IEnumerable 1)            в System.Linq.Enumerable.ToList [TSource] (источник IEnumerable`1)            в TestApplication.MainWindow.Window_Loaded (отправитель объекта, RoutedEventArgs e) в D:\RailwayProjects\RelayAnalysis\TestApplication\MainWindow.xaml.cs: строка 33       InnerException:

4b9b3361

Ответ 1

Я думаю, что foreignKey должен быть Id, а не StandardRack_id. Кроме того, вы должны использовать виртуальные, чтобы иметь возможность использовать ленивую загрузку.

Это работает для меня

using System.ComponentModel.DataAnnotations;
using System.Data.Entity;

namespace Racks
{

    public class StandardRack
    {
        public int Id { get; set; }
        public virtual StandardRelay StandardRelay { get; set; }
    }

    public class StandardRelay
    {
        public int Id { get; set; }

        public int StandardRack_Id { get; set; }

        [ForeignKey("Id")]
        [Required]
        public virtual StandardRack StandardRack { get; set; }
    }

    public class Context : DbContext
    {
        static Context()
        {
            Database.SetInitializer<Context>(null);
        }

        public DbSet<StandardRack> StandardRacks { get; set; }
        public DbSet<StandardRelay> StandardRelays { get; set; }

    }

    class Program
    {
        static void Main(string[] args)
        {
            var context = new Context();
            context.Database.Delete();
            context.Database.Create();

            var standardRack = new StandardRack();
            standardRack.StandardRelay = new StandardRelay();

            context.StandardRacks.Add(standardRack);
            context.SaveChanges();
        }
    }
}

Ответ 2

Индивидуальные ассоциации внешних ключей не поддерживаются Entitiy Framework. Вы должны удалить внешний ключ и использовать общие первичные ключи (первичный ключ зависимого - это его внешний ключ для принципала одновременно):

public class StandardRack {
    public int Id {get;set}
    public StandardRelay StandardRelay {get;set} 
}

public class StandardRelay {
    public int Id {get;set} 
    public StandardRack StandardRack { get; set; }
}

Отображение в Fluent API:

modelBuilder.Entity<StandardRack>()
    .HasOptional(rack => rack.StandardRelay)
    .WithRequired(relay => relay.StandardRack);

(Я утверждаю, что StandardRack имеет необязательное реле.)

Ответ 3

Вот как вы можете указать отношения "один к одному" с FK, используя беглый api.

Обратите внимание, что FK явно не определен в Enitity, но он определен с использованием свободного api.

public class StandardRack {
    public int Id {get;set}
    public StandardRelay StandardRelay {get;set} 
}

public class StandardRelay {
    public int Id {get;set} 
    public StandardRack StandardRack { get; set; }
}


modelBuilder.Entity<StandardRack>()
            .HasOptional(x => x.StandardRelay)
            .WithOptionalPrincipal(y => y.StandardRack)
            .Map(configurationAction: new Action<ForeignKeyAssociationMappingConfiguration>(x => x.MapKey("StandardRack_Id")));

Свободный api добавит столбец StandardRack_Id в StandardRelay.

Обратите внимание, что имя метода WithOptionalPrincipal() довольно иронично. msdn документация WithOptionalDependent должна прояснить.