Entity Framework Code сначала генерирует странную схему базы данных при использовании интерфейсов - PullRequest
0 голосов
/ 09 мая 2011

У меня есть следующие классы и интерфейсы ..

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

 public class Book :ITaggable
    {
        [DatabaseGenerated(DatabaseGenerationOption.Identity)] 
        public Guid BookId { get;set; }
        public string Title { get; set; }
        public string Author { get; set; }
        public virtual ICollection<Tag> Tags {get; set;}
    }

public class Pen:ITaggable
    {
        [DatabaseGenerated(DatabaseGenerationOption.Identity)]
        public Guid PenId { get; set; }
        public string Color { get; set; }
        public virtual ICollection<Tag> Tags {get; set;}
    }

public class Tag
    {
        [DatabaseGenerated(DatabaseGenerationOption.Identity)] 
        public Guid TagId { get; set; }
        public string Name { get; set; }
        public virtual ICollection<ITaggable> Items { get; set; }
    }

Для приведенной выше модели генерируется следующая структура таблицы

Книга -> BookId, название, автор

Ручка -> PenId, Цвет

Метка -> TagId, Имя, BookBookId, PenPenId

И когда я вставляю следующие данные

            Tag tag = new Tag();
            tag.Name = "Stationary";

            Book b1 = new Book();
            b1.Title = "Head first c#";
            b1.Author = "Betty";
            b1.Tags = new List<Tag>() { tag };

            Book b2 = new Book();
            b2.Title = "Head first Java";
            b2.Author = "Katty";
            b2.Tags = new List<Tag>() { tag };

            Pen p = new Pen();
            p.Color = "Red";
            p.Tags = new List<Tag>() { tag };

            context.Books.Add(b1);
            context.Books.Add(b2);
            context.Pens.Add(p);
            context.SaveChanges();

Он не вставляет данные тега для второй книги

Что я хочу сделать, так это то, что я хочу реализовать систему маркировки из трех таблиц показано здесь придерживаясь структуры моего класса

1 Ответ

1 голос
/ 09 мая 2011

Да, он не будет хранить информацию о теге для одной из книг, потому что ваш экземпляр тега может быть связан только с одной книгой.Это потребовало бы вашего отношения «многие ко многим» между Book и Tag, но ваше отношение «один ко многим».Отношение между Pen и Tag также один-ко-многим.Это ясно видно по внешним ключам в таблице Tag.

Проблема в том, что ICollection<ITaggable> Items сначала пропускается кодом EF - сначала код не работает с интерфейсами.Вы должны определить свой тег как:

public class Tag
{
    [DatabaseGenerated(DatabaseGenerationOption.Identity)] 
    public Guid TagId { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Book> Books { get; set; }
    public virtual ICollection<Pen> Pens { get; set; }
}

Это отобразит многие ко многим между Book и Tag и многие ко многим между Pen и Tag.Если вы также хотите собрать ITaggable, вы можете выставить другое свойство, объединяющее Books и Pens.

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

public class Tag
{
    [DatabaseGenerated(DatabaseGenerationOption.Identity)] 
    public Guid TagId { get; set; }
    public string Name { get; set; }
    public virtual Book Book { get; set; }
    public virtual Pen Pen { get; set; }
}

Снова вы можете создать Items как вычисляемое свойство.Любая комбинация отношений должна быть очевидна из этих примеров.

Редактировать:

Если вы не хотите предоставлять свойства навигации в теге, вы должны использовать fluent-api:

public class Context : DbContext
{
    public DbSet<Book> Books { get; set; }
    public DbSet<Pen> Pens { get; set; }
    public DbSet<Tag> Tags { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Book>()
                    .HasMany(b => b.Tags)
                    .WithMany();

        modelBuilder.Entity<Pen>()
                    .HasMany(p => p.Tags)
                    .WithMany();
    }
}

Дополнительную справку по API можно найти в блоге команды ADO.NET , но это не относится к данным (это для CTP5).

...