Entity Framework Code First ассоциации / FK проблемы и предположения / значения по умолчанию - PullRequest
3 голосов
/ 03 октября 2011

Меня очень смущает то, как Entity Framework может выяснить отношения между сущностями. У меня есть несколько вопросов по этому поводу.

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

  1. Есть много фотографий, каждая из которых принадлежит человеку (у человека может быть больше одной).
  2. Есть много заметок, каждая из которых принадлежит человеку (у человека может быть больше одной).
  3. и, наконец, у человека есть логотип, который является картиной.

.

    public class Person
    {
        public int ID { get; set; }

        public string name { get; set; }

        public Picture logo { get; set; }
    }

    public class Note
    {

        public int ID { get; set; }

        public string Text { get; set; }

        public Person Owner { get; set; }
    }


 public class Picture
    {

        public int ID { get; set; }

        public string Path { get; set; }

        public Person Owner { get; set; }
    }

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

(Если я опускаю поле Person.logo, скомпилирую / запускаю, затем вручную добавляю его в SQL вместе с отношением FK, оно работает на 100%, как и ожидалось ... Мне просто не удается понять, как установить это из самой EF).

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

Однако, теперь у меня есть один ко многим и много к одному (я не думаю, что это классифицируется как много ко многим?), Я просто не понимаю, как создавать объекты людей, где FK не является nullable и FK еще не существует.

Решение, которое я нашел, которое мне действительно не нравится, - сделать столбец person.picture обнуляемым, затем создать человека, затем создать изображение, а затем назначить изображение для объекта person ... но в идеале Я не хочу, чтобы это обнулялось. Всегда должна быть картинка.

Ответы [ 3 ]

2 голосов
/ 04 октября 2011

Старый ответ при условии вашего отношения 1: 1:

Прокрутите вниз, чтобы получить ответ на свое разъяснение.

Вот два способа добиться этого, один из них - удалить перекрестную ссылку , применив 1: N .

    public class Person
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public virtual Picture Logo { get; set; }
    }

    public class Note
    {
        public int ID { get; set; }
        public string Text { get; set; }
    }


    public class Picture
    {
        public int ID { get; set; }
        public string Path { get; set; }
    }

Это действительно дешевое решение, вы, вероятно, не хотите больше заметок или фотографий, чем люди ...

Итак, используйте Аннотации данных , чтобы указать внешний ключ, это сохранит навигацию и 1: 1 .

    public class Person
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public virtual Picture Logo { get; set; }
    }

    public class Note
    {
        [Key, ForeignKey("Person")]
        public int OwnerID { get; set; }
        public string Text { get; set; }
        public virtual Person Owner { get; set; }
    }


    public class Picture
    {
        [Key, ForeignKey("Person")]
        public virtual int OwnerId { get; set; }
        public string Path { get; set; }
        public virtual Person Owner { get; set; }
    }

Как видите, из-за отношения 1: 1 картинка и заметка будут использовать один и тот же идентификатор. Если ваш ключ не имеет имени ID, вам нужно добавить KeyAttribute , в этом случае мы также добавим ForeignKeyAttribute .

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

Свойства ассоциации, помеченные как virtual, будут по умолчанию загружаться с отложенной загрузкой. Это означает, что если вы извлекаете сущность Product, информация о ее категории не будет извлекаться из базы данных до тех пор, пока вы не получите доступ к ее свойству Category (или если вы явно не укажете, что данные категории должны извлекаться при написании запроса LINQ для извлечения Товарный объект).

* 1 035 * & mdash;
Скотт Гу - Использование EF Code First с существующей базой данных

Новый ответ относительно вашего разъяснения:

Продолжаем строить внешние ключи, возвращаясь к структуре 1: N с ICollection<T>; как только вы наберете своего человека, например var boss = Person.Find(BossID), вы сможете получить доступ к boss.Pictures, в котором будут различные изображения. Вы также можете назначить boss.Logo одной из этих картинок.

    public class Person
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public virtual Picture Logo { get; set; }
        public ICollection<Picture> Pictures { get; set; }
        public ICollection<Note> Notes { get; set; }
    }

    public class Note
    {
        public int ID { get; set; }
        [ForeignKey("Person")]
        public int OwnerID { get; set; }
        public string Text { get; set; }
        public virtual Person Owner { get; set; }
    }


    public class Picture
    {
        public int ID { get; set; }
        [ForeignKey("Person")]
        public virtual int OwnerId { get; set; }
        public string Path { get; set; }
        public virtual Person Owner { get; set; }
    }
1 голос
/ 03 октября 2011

Возможно, вас заинтересуют ваши члены-данные, используя DataAnnotations , а также ознакомьтесь с действующими Соглашениями для Code First .

0 голосов
/ 06 июля 2012
public class Person 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public virtual Picture Logo { get; set; } 
    public ICollection<Picture> Pictures { get; set; } 
    public ICollection<Note> Notes { get; set; } 
} 

public class Note 
{ 
    public int ID { get; set; } 

    public int OwnerID { get; set; } 
    public string Text { get; set; } 
    [ForeignKey("OwnerId")] 
    public virtual Person Owner { get; set; } 
} 


public class Picture 
{ 
    public int ID { get; set; } 

    public virtual int OwnerId { get; set; } 
    public string Path { get; set; } 
    [ForeignKey("OwnerId")] 
    public virtual Person Owner { get; set; } 
} 

Приведенный выше код верен, после нескольких попыток ввода неправильного кода, я получил правильный код.

Надеюсь, это полезно для вас.

...