2013-12-17 10 views
6

Я разрабатываю свое первое приложение для сущности-рамки. Я использую EF vesion 6 (от Nuget) и .net 4.0. Тем не менее, у меня есть некоторые трудности с чем-то, что для меня, похоже, должно быть необычайно простым. Я нашел много противоречивых советов и решений в Интернете, но, проведя несколько дней, пытаясь разобраться в этом, я действительно смущен и досконально допрошу некоторые основные понимания, которые у меня есть в Entity Framework. Я хочу сделать следующее: создать простой набор связанных объектов и автоматически удалить их, когда они будут удалены из родителя.Entity Framework 6 и коллекции

Вот как я смоделировал бы это в ваниле C#. В соответствии с образцами Microsoft, предположим, что у нас есть два класса, почт и тегов, например:

public class Post 
{ 
    public string Name { get; set; } 
    public string Author { get; set; } 

    public ICollection<Tag> Tags { get; set; } 
} 

public class Tag 
{ 
    public string Text { get; set; } 
    // Possibly other properties here 
} 

Затем, добавив тег так же просто, как myPost.Tags.Add(myTag) и удаление тега так просто, как myPost.Tags.Remove(myTag).

Теперь в сторону сущности Framework: я посмотрел на это и подумал «Внешний ключ, конечно!». но у меня было множество проблем с добавлением FK: теги не удаляли из базы данных, когда они удалялись из сообщения, myPost.Tags имел бы 0 элементов при загрузке из db, несмотря на то, что SQL explorer показал, что значение PostId верное, и т. д. Я сбился с кучей трюков, например, маркировал Tag.PostId в качестве ключа, вручную удаляя теги, фактически добавляя тег в контекст как DbSet, вручную устанавливая myTag.Post = null; (я пытался с Lazy загружать как включенные, так и отключенные, для чего это стоит, хотя я бы хотел, чтобы это было возможно)

Теперь (спасибо в немалой степени, казалось бы, конфликтующим и чрезмерно сложным примерам), я довольно смущен и потерян. Может ли кто-нибудь сказать мне, как мне следует настраивать эти отношения в EF? (Я использую Code First, кстати)

РЕШЕНИЕ:

Благодаря Мох, я пришел с этой структурой, которая делает именно то, что я хочу:

public class Post 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string Author { get; set; } 

    public virtual ICollection<Tag> Tags { get; set; } 

    public Post() 
    { 
     Tags = new HashSet<Tag>(); 
    } 
} 

public class Tag 
{ 
    [Key, Column(Order=1), DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 
    public string Text { get; set; } 
    // Possibly other properties here 

    public virtual Post Post { get; set; } 
    [Key, Column(Order=2)] 
    public virtual int PostId { get; set; } 
} 

public class TestContext : DbContext 
{ 
    public DbSet<Post> Posts { get; set; } 
} 

Когда Tag удаляется из Метки коллекции Post «s, Entity Framework будет выдавать DELETE для тега, как описано здесь (# 2): http://www.kianryan.co.uk/2013/03/orphaned-child/

Кроме того, добавление тега к сообщению будет автоматически выдавать INSERT и установить отношения FK бедра.

Замечание: Обязательно используйте virtual! Я думаю, что это был корень многих моих разочарований.

+0

Вы не поместили свойство 'Id' и EF сделали отношения? Можете ли вы привести нам пример того, как вы выполняете свои запросы? – Tico

+0

@Tico Я оставил материал для внедрения EF, который был умышленным - я хотел избежать любых негативных эффектов/предубеждений из моей реальной реализации (не говоря уже об изменении, которое я немного изменил, как я его поиграл!), Чтобы я мог чтобы получить советы о том, как настроить его прямо с самого начала. Такая же история с моими примерными запросами, хотя я предполагаю, что мой пример использования выглядит следующим образом: «1) Сообщение, созданное с помощью некоторых начальных тегов. 2) Теги тегов редактируются, некоторые удалены, некоторые добавлены. 3) Сообщение сохраняется». – Xcelled194

+0

Итак, я предполагаю, что вы знакомы с Контекстом и т. Д. Так как у вас есть некоторые данные в SQL. Используйте LINQ для запроса одного из них. Если он по-прежнему возвращает «null», может быть что-то не так с вашими запросами. – Tico

ответ

2

Просьба также определить соотношение сторон с Tag, а также указать, что каждый Tag относится к одному Post и не требуется.

Добавить требуемое свойство навигации для Post в Tag:

public class Tag 
{ 
    // you need an ID 
    public int Id { get; set; } 

    public string Text { get; set; } 

    [Required] 
    public virtual Post Post { get; set; } 
} 

В качестве альтернативы, если вы действительно не хотите, чтобы добавить свойства навигации, вы можете использовать Fluent API:

modelBuilder.Entity<Post>().HasMany(p => p.Tags).WithRequired(); 
+0

Обычно я добавляю 'Id' для свойства навигации. – Tico

+0

Я имел в виду, что для ваших сущностей требуется поле идентификатора первичного ключа; предположил, что вы оставили их для краткости – Moho

+0

'[Обязательный]' DataAnnotation используется для создания требуемой связи. То, что я имел в виду, было 'public virtual Post Post {get; задавать; } ', а также свойство, подобное:' public int PostId {get; задавать; } '. Когда я ищу объект, у меня есть только 'Id'. Если я ищу «сообщение», он вернет «null» – Tico

0

Это, вероятно, некромантия нитей, но у меня нет комментариев просто комментировать. Не будут ли делать то, что вам нужно?

public class Tag 
{ 
    [Key, Column(Order=1), DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 
    public string Text { get; set; } 
    // Possibly other properties here 

    public int PostId { get; set; } 

    [ForeignKey("PostId")] 
    public virtual Post Post { get; set; } 

} 

сообщения дан загружается из базы данных, затем используется в качестве внешнего ключа (через аннотацию) в классе Post. Сообщение виртуальное, ничего больше. Возможно, вы могли бы просто пойти с основной аннотацией [Key].

+0

EF автоматически идентифицирует свойство с именем 'ID' как уникальный идентификатор для класса, поэтому вы являетесь избыточным. Кроме того, API Fluent, кажется, лучше (более надежно) при описании отношений, чем декорации на свойствах. Кроме того, определение ваших отношений в DbContext (а также остальное ваше описание персистентности в других файлах доступа к данным) позволяет вам уйти от EF на более позднюю дату с небольшими изменениями. –

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