Linq To Sql多次加入表

时间:2022-10-05 11:38:55

I am a somewhat experienced Rails developer and I thought I would try out ASP.NET's version of MVC. In doing so I also decided to try Linq->Sql...

我是一个有点经验的Rails开发人员,我想我会试用ASP.NET的MVC版本。这样做我还决定尝试Linq-> Sql ...

I am a bit confused about the way Linq->Sql handles joins.

我对Linq-> Sql处理连接的方式感到有点困惑。

A trivial example of my schema is :

我的架构的一个简单例子是:

books:
id
title

书籍:id标题

categories:
id
name

类别:id名称

books_categories:
book_id
category_id

books_categories:book_id category_id

Simply dragging these tables to the .dbml file doesn't seem to do it. I get a property on my Book class books_categories, what I expect is a property that I can iterate over and get Category classes directly.

只需将这些表拖到.dbml文件中似乎就不会这样做。我在Book class books_categories上获得了一个属性,我期望的是一个属性,我可以迭代并直接获得Category类。

Right now I have to do something that feels very wrong

现在我必须做一些感觉非常错误的事情

        foreach (books_categories bc in book.books_categories)
        {
            category_names.Add(bc.Category.category.Trim());
        }

[In Response to Accepted answer]
I grudgingly accepted the answer of "write your own glue code". After continuing my research of Linq->Sql I discovered that it is apparently slowly being let go in favor of the (more powereful, IMO) Entity Framework. EF still allows one to use LINQ for queries and does a decent job of figuring out relationships like Ruby's ActiveRecord.

[回复接受的答案]我勉强接受了“编写自己的胶水代码”的答案。在继续我对Linq-> Sql的研究之后,我发现它显然正在慢慢放弃(更强大的IMO)实体框架。 EF仍允许使用LINQ进行查询,并且可以很好地找出像Ruby的ActiveRecord这样的关系。

4 个解决方案

#1


8  

Use a partial class implementation for Book and add appropriate methods for categories and their properties. Have the properties front-end the Books_Categories property (you can make this have private visibility to force implementation through your Categories property).

使用Book的部分类实现,并为类别及其属性添加适当的方法。将属性作为Books_Categories属性的前端(您可以使其具有私有可见性,以通过您的Categories属性强制实现)。

public partial class Books
{
    public IEnumerable<string> CategoryNames
    {
       get
       {  
            return this.Books_Categories
                       .Select( bc => bc.Category.category.Trim() );
       }
    }

    public void AddCategory( Category category )
    {
       this.Books_Categories.Add( new Book_Category
                                  {
                                      Category = category,
                                      Book = this
                                  } );
    }

    public void RemoveCategory( Category category )
    {
       var bc = this.Book_Categories
                    .Where( c => c.Category == category )
                    .SingleOrDefault();
       this.Books_Categories.Remove( bc );
    }
}

Obviously, you'll need to add some error/bounds checking, etc. but you get the idea.

显然,你需要添加一些错误/边界检查等,但你明白了。

I'll grant you this is not ideal, but at least you have the flexibility to determine how it works.

我会告诉你这不是理想的,但至少你可以灵活地确定它是如何工作的。

#2


2  

Many to many mappings are explicitly supported in the Entity Framework, but not in LINQ to SQL. You can also use third-party ORMs such as NHibernate.

实体框架中明确支持多对多映射,但LINQ to SQL中不支持。您还可以使用NHibernate等第三方ORM。

#3


0  

I don't think your expected result is supported in Linq to Sql.

我不认为Linq to Sql支持您的预期结果。

What you're doing may feel wrong, but I think that's one way to work around that limitation of L2S.

你在做什么可能会感觉不对,但我认为这是解决L2S限制的一种方法。

Man, i've really got to get into Rails...

伙计,我真的要进入Rails ......

#4


0  

What you can do if you want to create a book and directly want to add a category to it is: in your view:

如果您想要创建一本书并直接想要为其添加类别,您可以执行以下操作:在您的视图中:

        <p>
            <label for="CategorySelect">Category:</label>
            <%= Html.ListBox("CategorySelect") %>
            <%= Html.ValidationMessage("CategorySelect", "*")%>
        </p>  

in your bookscontroller:

在你的bookcontroller中:

        public ActionResult New()
    {
            var data = _entities.Categories.ToList();
        ViewData["CategorySelect"] = new MultiSelectList(data, "Id", "Name");
}

        [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult New([Bind(Exclude = "Id")] Book Booknew)
    {
        IEnumerable<int> selectedCategories = Request["CategorySelect"].Split(new Char[] { ',' }).Select(idStr => int.Parse(idStr));

        if (!ModelState.IsValid)
            return View();

        try {
            foreach(var item in selectedCategories){
                BooksCategories bc = new BooksCategories();
                bc.Book = Booknew;
                bc.CategoryId = item;
                _entities.BooksCategories.InsertOnSubmit(bc);
            }
            _entities.Books.InsertOnSubmit(Booknew);
            _entities.SubmitChanges();

#1


8  

Use a partial class implementation for Book and add appropriate methods for categories and their properties. Have the properties front-end the Books_Categories property (you can make this have private visibility to force implementation through your Categories property).

使用Book的部分类实现,并为类别及其属性添加适当的方法。将属性作为Books_Categories属性的前端(您可以使其具有私有可见性,以通过您的Categories属性强制实现)。

public partial class Books
{
    public IEnumerable<string> CategoryNames
    {
       get
       {  
            return this.Books_Categories
                       .Select( bc => bc.Category.category.Trim() );
       }
    }

    public void AddCategory( Category category )
    {
       this.Books_Categories.Add( new Book_Category
                                  {
                                      Category = category,
                                      Book = this
                                  } );
    }

    public void RemoveCategory( Category category )
    {
       var bc = this.Book_Categories
                    .Where( c => c.Category == category )
                    .SingleOrDefault();
       this.Books_Categories.Remove( bc );
    }
}

Obviously, you'll need to add some error/bounds checking, etc. but you get the idea.

显然,你需要添加一些错误/边界检查等,但你明白了。

I'll grant you this is not ideal, but at least you have the flexibility to determine how it works.

我会告诉你这不是理想的,但至少你可以灵活地确定它是如何工作的。

#2


2  

Many to many mappings are explicitly supported in the Entity Framework, but not in LINQ to SQL. You can also use third-party ORMs such as NHibernate.

实体框架中明确支持多对多映射,但LINQ to SQL中不支持。您还可以使用NHibernate等第三方ORM。

#3


0  

I don't think your expected result is supported in Linq to Sql.

我不认为Linq to Sql支持您的预期结果。

What you're doing may feel wrong, but I think that's one way to work around that limitation of L2S.

你在做什么可能会感觉不对,但我认为这是解决L2S限制的一种方法。

Man, i've really got to get into Rails...

伙计,我真的要进入Rails ......

#4


0  

What you can do if you want to create a book and directly want to add a category to it is: in your view:

如果您想要创建一本书并直接想要为其添加类别,您可以执行以下操作:在您的视图中:

        <p>
            <label for="CategorySelect">Category:</label>
            <%= Html.ListBox("CategorySelect") %>
            <%= Html.ValidationMessage("CategorySelect", "*")%>
        </p>  

in your bookscontroller:

在你的bookcontroller中:

        public ActionResult New()
    {
            var data = _entities.Categories.ToList();
        ViewData["CategorySelect"] = new MultiSelectList(data, "Id", "Name");
}

        [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult New([Bind(Exclude = "Id")] Book Booknew)
    {
        IEnumerable<int> selectedCategories = Request["CategorySelect"].Split(new Char[] { ',' }).Select(idStr => int.Parse(idStr));

        if (!ModelState.IsValid)
            return View();

        try {
            foreach(var item in selectedCategories){
                BooksCategories bc = new BooksCategories();
                bc.Book = Booknew;
                bc.CategoryId = item;
                _entities.BooksCategories.InsertOnSubmit(bc);
            }
            _entities.Books.InsertOnSubmit(Booknew);
            _entities.SubmitChanges();