Код Entity Framework 4.1 Первый подход к созданию отношения «многие ко многим»

Я использую Silverlight 5 Beta SDK и EntityFramework 4.1 в приложении Silverlight.

Я попытаюсь создать две таблицы «Автор» и «Книга». В SQL должна быть третья (объединяющая) таблица, которая создает отношение «многие ко многим» между «Автор» и «Книга» (один автор может написать много книг, а книга может быть написана многими авторами).

Это то, что у меня есть до сих пор:

namespace CodeFirst.Models.Web
{    
    public class Author
    {
        public Author()
        {
            this.Books = new HashSet<Book>();
        }

        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Key]
        public int ID { get; set; }

        [Required]
        public string Name { get; set; }

        public ICollection<Book> Books { get; set; }
    }


    public class Book
    {
        public Book()
        {
            this.Authors = new HashSet<Author>();
        }


        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        [Key]
        public int ID { get; set; }

        [Required]
        public string Name { get; set; }

        public ICollection<Author> Authors { get; set; }
    }


    // Should I do something like that:
    public class AuthorMapping : EntityTypeConfiguration<Author>
    {
        public AuthorMapping() : base()
        {   
            //this.HasMany (g => g.Books)
            //    .WithMany(m => m.Authors)
            //    .Map     (gm => gm.ToTable    ("Author_Book")
            //                      .MapLeftKey ("AuthorID")
            //                      .MapRightKey("BookID"));
        }
    }


    public class CodeFirstModelContext : DbContext
    {
        public CodeFirstModelContext() : base()
        {
            this.Database.Connection.ConnectionString = @".\MSSQLSERVER2008;Database=CodeFirst;Trusted_Connection=true;";
        }


        public DbSet<Author> Authors  { get; set; }
        public DbSet<Book>   Books { get; set; }


        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new AuthorMapping());

            // tell Code First to ignore PluralizingTableName convention
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
    }


    [EnableClientAccess()]
    public class CodeFirstDomainService : DomainService
    {
        public CodeFirstDomainService()
        {
            this.m_modelContext = new CodeFirstModelContext();
        }


        public IQueryable<Author> GetAuthors()
        {
            return this.m_modelContext.Authors;//.Include("Books");
        }

        public void InsertAuthor(Author Author)
        {
            this.m_modelContext.Insert(Author);
        }

        public void UpdateAuthor(Author Author)
        {
            this.m_modelContext.Update(Author, this.ChangeSet.GetOriginal(Author));
        }

        public void DeleteAuthor(Author Author)
        {
            this.m_modelContext.Delete(Author);
        }


        public IQueryable<Book> GetBooks()
        {
            return this.m_modelContext.Books;//.Include("Authors");
        }

        public void InsertBook(Book Author)
        {
            this.m_modelContext.Insert(Author);
        }

        public void UpdateBook(Book Author)
        {
            this.m_modelContext.Update(Author, this.ChangeSet.GetOriginal(Author));
        }

        public void DeleteBook(Book Author)
        {
            this.m_modelContext.Delete(Author);
        }


        protected override void Dispose(bool disposing)
        {
            if (disposing)
                this.m_modelContext.Dispose();
            base.Dispose(disposing);
        }

        protected override bool PersistChangeSet()
        {
            this.m_modelContext.SaveChanges();
            return base.PersistChangeSet();
        }


        private CodeFirstModelContext m_modelContext;
    }
}

Наиболее очевидная проблема заключается в том, что свойства навигации (Книги в Авторе и Авторы в Книге) не создаются дизайнером кода в моем клиентском проекте.

Что мне нужно сделать?

EDIT: Хорошо, теперь я могу одновременно использовать только один из NavigationProperties. Если я попытаюсь «включить» оба, я получаю следующую ошибку:

Association 'Author_Book' defined on entity type 'CodeFirst.Models.Web.Author' is invalid. It is a foreign key association but the property type is not a singleton.

Это мой обновленный код:

public class Author
{
    public Author()
    {
        this.Books = new Collection<Book>();
    }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key]
    public int ID { get; set; }

    [MaxLength(32)]
    [Required]
    public string Name { get; set; }

    [Association("Author_Book", "ID", "ID")]
    [Include]
    public Collection<Book> Books { get; set; }
}


public class Book
{
    public Book()
    {
        this.Authors = new Collection<Author>();
    }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key]
    public int ID { get; set; }

    [MaxLength(32)]
    [Required]
    public string Name { get; set; }

    [Association("Author_Book", "ID", "ID")]
    [Include]
    public Collection<Author> Authors { get; set; }
}


public class AuthorMapping : EntityTypeConfiguration<Author>
{
    public AuthorMapping() : base()
    {
        this.HasMany (g => g.Books)
            .WithMany(m => m.Authors)
            .Map     (gm => gm.ToTable("Author_Book"));
    }
}

public class BookMapping : EntityTypeConfiguration<Book>
{
    public BookMapping() : base()
    {
        this.HasMany (m => m.Authors)
            .WithMany(g => g.Books)
            .Map     (gm => gm.ToTable("Author_Book"));
    }
}

Мне кажется, что Entity Framework до сих пор не умеет работать с отношениями «многие ко многим». По крайней мере, это то, что подразумевает сообщение об ошибке.

EDIT2: я изменил свой код после того, как прочитал этот пост в social.msdn:

public class Author
{
    public Author()
    {
        this.Books = new Collection<Book>();
    }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key]
    public int ID { get; set; }

    [MaxLength(32)]
    [Required]
    public string Name { get; set; }

    [Association("Author_Book", "Book_ID", "Author_ID")]
    [Include]
    [ForeignKey("Book_ID")]
    public Collection<Book> Books { get; set; }
    public int Book_ID { get; set; }
}

public class Book
{
    public Book()
    {
        this.Authors = new Collection<Author>();
    }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key]
    public int ID { get; set; }

    [MaxLength(32)]
    [Required]
    public string Name { get; set; }

    [Association("Author_Book", "Author_ID", "Book_ID")]
    [Include]
    [ForeignKey("Author_ID")]
    public Collection<Author> Authors { get; set; }
    public int Author_ID { get; set; }
}

Это не решает мою проблему. Та же ошибка все еще присутствует. Я безуспешно пытался удалить AssociationAttribute. Я делаю что-то не так здесь?


person 0xbadf00d    schedule 09.05.2011    source источник
comment
@Caglar Gonul: Спасибо за ваш ответ, но я не понимаю, как это относится к моей проблеме. Я не расширяю и не сопоставляю существующую базу данных или таблицу. Я использую Code First для создания таблицы из кода с помощью Entity Framework.   -  person 0xbadf00d    schedule 09.05.2011
comment
›дизайнер кода в моем клиентском проекте. Какие? Вы используете WCF? Можете ли вы показать нам таблицы, которые генерируются этим?   -  person Euphoric    schedule 09.05.2011


Ответы (1)


Я думаю, что проблема здесь заключается в службе WCF RIA, а не в чем-либо, связанном с EF. То есть этот WCF не любит интерфейсы. Решением будет использование Collection вместо ICollection. Я уверен, что EF не будет возражать и решит вашу проблему с WCF.

Изменить: это может решить вашу проблему http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/d894c8af-5985-4995-88e2-c8733e4a51ea

person Euphoric    schedule 09.05.2011
comment
+1 | Да, это сработало. К сожалению, это очень неясно и почти недокументировано. Большое спасибо! - person 0xbadf00d; 10.05.2011
comment
Хорошо, теперь я получаю другую ошибку. Я отредактировал свой первоначальный пост. - person 0xbadf00d; 10.05.2011
comment
Я думаю, вы должны открыть новый вопрос только с новой проблемой. - person Euphoric; 10.05.2011
comment
stackoverflow.com/questions/5961672/ - person 0xbadf00d; 11.05.2011