虽然你可以在Author中实现相同的功能(因为每个作者都可以有多本书),但是使用authorId取代bookId:
[Table( Name = "Authors" )]
public class Author
{
...
private EntitySet _bookAuthors = new EntitySet( );
[Association( Name = "FK_BookAuthors_Authors",
Storage = "_bookAuthors",
OtherKey = "authorId", ThisKey = "Id" )]
private ICollection BookAuthors {
get { return _bookAuthors; }
set { _bookAuthors.Assign( value ); }
}
public class Author
{
...
private EntitySet _bookAuthors = new EntitySet( );
[Association( Name = "FK_BookAuthors_Authors",
Storage = "_bookAuthors",
OtherKey = "authorId", ThisKey = "Id" )]
private ICollection BookAuthors {
get { return _bookAuthors; }
set { _bookAuthors.Assign( value ); }
}
2. 添加一个公有属性,通过1:M的关系使用LINQ 来检索枚举数据。
最后,通过创建Authors属性从该书实例的私有书作者列表中检索所有作者。例如,如果你有一本LINQ In Action的书,该书就有三个作者:Fabrice Marguerie, Steve Eichert, 和Jim Wooley,那么LINQ In Action Book实例将包涵三个BookAuthors的列表:
你想要做的就是检索作者列表,因此调用者甚至不必了解有这样一个中间表的存在。你可以通过使用LINQ来查询该私有BookAuthors属性并仅仅返回所查找的作者:
IEnumerable authors = from ba in BookAuthors
select ba.Author;
select ba.Author;
现在,你可以在Book中将其包装成一个名位为Authors的公有、只读属性,并且(可选)通过在结果集中调用toList()返回一个ICollection集合,正如我在这里所实现的那样,为其提供一些更多的公共接口:
public ICollection Authors { get {
return ( from ba in BookAuthors select ba.Author ).ToList( ); } }
return ( from ba in BookAuthors select ba.Author ).ToList( ); } }
当然,在Author中你可以实现相同的功能来返回一个作者的所有书籍:
public ICollection Books { get {
return ( from ba in BookAuthors select ba.Book ).ToList( ); } }
return ( from ba in BookAuthors select ba.Book ).ToList( ); } }
从M:M的关系中访问数据
现在,你可以完全地如愿操作你的对象模型。下面是一些例子:
// Starting from Books...
foreach( var book in bookCatalog.Books ) {
string title = book.Title;
decimal price = book.Price;
string category = book.Category.Name;
ICollection authors = book.Authors;
ICollection otherBooksInCategory = book.Category.Books;
}
// Starting from Authors...
foreach( var author in bookCatalog.Authors ) {
string name = author.Name;
ICollection books = author.Books;
}
// Starting from Categories...
foreach( var category in bookCatalog.Categories ){
string name = category.Name;
foreach( var book in category.Books ){
string bookTitle = book.Title;
ICollection bookAuthors = book.Authors;
}
}
foreach( var book in bookCatalog.Books ) {
string title = book.Title;
decimal price = book.Price;
string category = book.Category.Name;
ICollection authors = book.Authors;
ICollection otherBooksInCategory = book.Category.Books;
}
// Starting from Authors...
foreach( var author in bookCatalog.Authors ) {
string name = author.Name;
ICollection books = author.Books;
}
// Starting from Categories...
foreach( var category in bookCatalog.Categories ){
string name = category.Name;
foreach( var book in category.Books ){
string bookTitle = book.Title;
ICollection bookAuthors = book.Authors;
}
}
从未使用/分配警告
有件事情你可能需要注意的是你为LINQ创建的中间变量(虽然仅仅获得了对Association特性的引用,但是其它部分从来未使用过)将会引起Visual Studio提示为警告,消息为这些值从未使用和分配。当然,它们实际上都被使用被进行了值的分配,但是后台编译器却不能探测到。你可以抑制这些警告的发生,正如我在附件代码中阐述的那样,使用pragma 预处指令取代上面需要映射到数据库的每个类或字段:
// disable never used/assigned warnings for fields that are being used by LINQ
#pragma warning disable 0169, 0649
#pragma warning disable 0169, 0649