Не удалось определить основной конец связи между типами-ошибка Entity Framework, связь классов между одним и тем же классом

есть класс ниже, и попытаться найти записи в базе данных возвращает ошибку. Использование C #, MVC 4, Entity Framework 4 и базы данных SQL Server 2012.

Unable to determine the principal end of an association between the types 'FlexApp.Models.Model.Usuario' and 'FlexApp.Models.Model.Usuario'. 

The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

класс

public class Usuario
{
    [Key]
    public int UsuarioID { get; set; }
    public string Nome { get; set; }
    public int UsuCad { get; set; }        
    public int UsuAlt { get; set; }

    [ForeignKey("UsuCad")]
    public virtual Usuario UsuarioCad { get; set; }
    [ForeignKey("UsuAlt")]
    public virtual Usuario UsuarioAlt { get; set; }
}

база данных FK

alter table USUARIO add constraint USUARIO_fk01 foreign KEY(UsuCad) REFERENCES USUARIO(UsuarioID);
alter table USUARIO add constraint USUARIO_fk02 foreign KEY(UsuAlt) REFERENCES USUARIO(UsuarioID);

3 ответов


ответ

после поиска много, я нашел отзыв об использовании InverseProperty Тогда код выглядит так. Это свойство ForeignKey это монтировать ссылку и свойство InverseProperty для того, чтобы сообщить, что поле зависит от этого другого лагеря, обращая на внешний ключ.

Спасибо за помощь

public class Usuario
{
    [Key]
    public int UsuarioID { get; set; }
    public string Nome { get; set; }
    public int UsuCad { get; set; }        
    public int UsuAlt { get; set; }

    [ForeignKey("UsuCad")]
    [InverseProperty("UsuarioID")]
    public virtual Usuario UsuarioCad { get; set; }
    [ForeignKey("UsuAlt")]
    [InverseProperty("UsuarioID")]
    public virtual Usuario UsuarioAlt { get; set; }
}

Я не на 100% уверен, какую схему БД вы пытаетесь достичь здесь. Я предполагаю, что вы хотите иметь внешний ключ к той же таблице. В своем комментарии Вы сказали, что хотите корабль отношений один к одному. Технически это невозможно. Потому что при попытке вставить первую запись необходимо указать значение для столбца внешнего ключа. Значение должно быть Id существующей записи. Ждать... У нас пока нет записей !

так как 1-1 не очень практично здесь вы должны делать отношения один к нулю/один. Это означает, что столбец внешнего ключа должен быть тип nullable, так что вы можете вставить свою первую запись с NULL значение в столбце внешнего ключа.

мне немного трудно понять вашу модель и имена свойств. Поэтому я собираюсь использовать общий класс / таблицу, которую каждый может понять, но с вашим конкретным требованием (внешний ключ собственной ссылки)

я не использую данные аннотации, я использую Fluent API

глупое деловое требование / предположение заключается в том, что:

  • один человек может или не может иметь родитель
  • один человек может или не может иметь ребенок

таким образом, наш класс сущностей будет выглядеть следующим образом

public class Person
{
    public int Id { set; get; }
    public string Name { set; get; }
    public virtual Person Parent { set; get; }
    public virtual Person Kid { set; get; }    
}

теперь, чтобы использовать fluent API для управления отношениями, нам нужно перейти к нашему классу DBContext и переопределить OnModelCreating метод

public class MyDbContext : DbContext
{
    public MyDbContext() : base("MyConnectionStringName") { }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {    
        modelBuilder.Entity<Person>().HasKey(d => d.Id)
            .HasOptional(m => m.Kid).WithOptionalPrincipal(d=>d.Parent);

        base.OnModelCreating(modelBuilder);
    }   

    public DbSet<Person> Persons { set; get; }
}

это создаст таблицу с 3 столбцами,ID, имя и Ид_родительского_объекта (NULLABLE, отношение внешнего ключа к ID таблицы)

Я могу вставить данные такой

var db = new MyDbContext();

var myMom = new Person {Name = "Indira"};
var me = new Person {Name = "Shyju", Parent = myMom};
var myDaughter = new Person { Name = "Gauri", Parent = me};

db.Persons.Add(myMom);
db.Persons.Add(me);
db.Persons.Add(myDaughter);

db.SaveChanges();

и у вас будут данные с столбцом ParentId, имеющим внешний ключ к столбцу ID той же таблицы.

enter image description here


ошибка заключается в том, что имя класса Usuario точно такой же, как в свойстве public virtual Usuario UsuarioAlt { get; set; }

нельзя использовать тот же тип, что и свойство навигации. Проблема здесь в том, что свойства навигации неверны. Подумайте о таблице базы данных SQL, может ли тот же уникальный первичный ключ быть внешним ключом в той же таблице? Вам нужен внешний ключ из другой таблицы.

свойства навигации-это то, что Entity Framework использует для определения реляционной модели сущности между вашими POCOs и, следовательно, вашими таблицами базы данных.

вы хотите другой класс по отношению. Если у вас есть второй класс с этим именем, используйте псевдоним пространства имен, чтобы среда выполнения могла знать разницу между двумя классами, теперь это похоже на класс, ссылающийся на себя .

вы должны написать свою модель, как показано ниже

public class Usuario
{
    [Key]
    public int UsuarioID { get; set; }
    public string Name { get; set; }
    public int UsuCad { get; set; }        
    public int UsuAlt { get; set; }
    public virtual SomeSecondClass SomeSecondClass { get; set; }
    public virtual SomeThirdClass SomeThirdClass { get; set; }
}

public class SomeSecondClass 
{
   public int SomeSecondClassID { get; set;}
   // More properties
}

public class SomeThirdClass 
{
   public int SomeThirdClassID { get; set;}
   // More properties
}