如何将一个或多个LINQ Lambda返回记录放入List?! C#

时间:2017-10-18 14:55:10

标签: c# linq lambda

这个我的代码和这个Action中的每一行都会做一些事情并从数据库中检索一些记录,让我举一个关于这个Action的例子,这个Action会显示Ordre和那个ordre下的产品,这意味着Ordre(1212) )可能有1个产品或多个产品,但我的代码只显示了该记录的一个记录而不是全部,所以我的问题是如何将此操作的返回记录列入列表?!或者我应该做别的事情!谁能指引我朝正确的方向发展? THX

控制器中的代码:

public ActionResult OrdreOpenDetails(string id)
{
    DataContext data_2 = new DataContext();
    Ordre_Open_Details_VM oodvm = new Ordre_Open_Details_VM();



    oodvm.SalesLine = data_2.Sales_Line.FirstOrDefault(n => n.Document_No_ == id);
    oodvm.SalesHeader = data_2.Sales_Header.FirstOrDefault(m => m.No_ == oodvm.SalesLine.Document_No_);
    oodvm.SalesPersonPurchasers = data_2.Salesperson_Purchasers.FirstOrDefault(h=>h.Code == oodvm.SalesHeader.Salesperson_Code);
    oodvm.SalesCommentLine = data_2.Sales_Comment_Line.FirstOrDefault(z => z.No_ == oodvm.SalesLine.Document_No_);
    oodvm.PurchaseLine = data_2.Purchase_Line.FirstOrDefault(t=>t.Document_No_ == oodvm.SalesLine.Købsordrenr_);



    return View(oodvm);
} 

我的ViewModel类:

  public class Ordre_Open_Details_VM
    {
        public Sales_Header SalesHeader { get; set; }
        public Sales_Line SalesLine { get; set; }
        public Purchase_Line PurchaseLine { get; set; }
        public Salesperson_Purchasers SalesPersonPurchasers { get; set; }
        public Sales_Comment_Line SalesCommentLine { get; set; }
    }

观点中的守则:

@model DBhandling.Ordre_Open_Details_VM


<h2>OrdreOpenDetails</h2>

<div class="content">
    <div class="container-fluid">
        <div class="row">
            <div class="col-lg-4 col-md-5">
                <div class="card">
                    <div class="card-header" data-background-color="purple">
                        <h4 class="title">Detaljer</h4>
                        @*<p class="category">Detaljer <span>»</span> Order nr <span>»</span> @Model.SalesInvoiceHeader.Order_No_</p>*@
                    </div>
                    <div class="card-content">
                        <form>

                            <div class="row">
                                <div class="col-md-6">
                                    <div class="form-group label-floating">
                                        <label>Order nr.</label>
                                        <input type="text" class="form-control border-input" disabled value="@Model.SalesHeader.No_">
                                    </div>
                                </div>
                                <div class="col-md-6">
                                    <div class="form-group label-floating">
                                        <label>vare nummer</label>
                                        <input type="text" class="form-control border-input" disabled value="@Model.SalesLine.No_">
                                    </div>
                                </div>
                            </div>
                            <div class="row">
                                <div class="col-md-6">
                                    <div class="form-group label-floating">
                                        <label>Forventet levering</label>
                                        <input type="datetime" class="form-control border-input" disabled value="@Model.SalesLine.Planned_Delivery_Date">
                                    </div>
                                </div>
                                <div class="col-md-6">
                                    <div class="form-group label-floating">
                                        <label>Forventet levering Direkte</label>
                                        <input type="datetime" class="form-control border-input" disabled value="@(Model.PurchaseLine != null ? Model.PurchaseLine.Planned_Receipt_Date :(DateTime?)null )">
                                    </div>
                                </div>
                                <div class="col-md-6">
                                    <div class="form-group label-floating">
                                        <label>Sales Person</label>
                                        <input type="text" class="form-control border-input" disabled value="@Model.SalesPersonPurchasers.Name">
                                    </div>
                                </div>

                            </div>
                            <div class="row">
                                <div class="col-md-12">
                                    <div class="form-group label-floating">
                                        <label>Comment</label>
                                        <input type="text" class="form-control border-input" disabled value="@(Model.SalesCommentLine != null ? Model.SalesCommentLine.Comment : "No Comment")">
                                    </div>
                                </div>
                            </div>


                            <div class="clearfix"></div>
                        </form>
                    </div>


                </div>

            </div>
        </div>
    </div>
</div>

2 个答案:

答案 0 :(得分:0)

编辑:我看到您的LINQ条件是基于SalesLine分配中设置的ID的值? (m => m.No_ == oodvm.SalesLine.Document_No_)这不是一个非常聪明的做法,更改此逻辑以根据数据本身中的ID选择订单,而不是基于您之前检索的内容,否则我所描述的方法将无效。我不知道你的数据是如何设置的,所以我只是要离开&#34; condition&#34;在SelectMany函数调用中。

您可以将视图模型类更改为包含每个对象的列表,而不仅仅是一个实例

public class Ordre_Open_Details_VM
{
    public List<Sales_Header> SalesHeader { get; set; }
    public List<Sales_Line> SalesLine { get; set; }
    public List<Purchase_Line> PurchaseLine { get; set; }
    public List<Salesperson_Purchasers> SalesPersonPurchasers { get; set; }
    public List<Sales_Comment_Line> SalesCommentLine { get; set; }
}

然后,您可以使用SelectMany Linq方法检索满足条件的所有订单。

oodvm.SalesLine = data_2.Sales_Line.SelectMany(condition);
oodvm.SalesHeader = data_2.Sales_Header.SelectMany(conditon);
oodvm.SalesPersonPurchasers = data_2.Salesperson_Purchasers.SelectMany(condition);
oodvm.SalesCommentLine = data_2.Sales_Comment_Line.SelectMany(condtion);
oodvm.PurchaseLine = data_2.Purchase_Line.SelectMany(condition);

以这种方式设置,oodvm的属性将包含多个订单,每个索引将对应一个条目。

所以

oodvm.SalesLine[0]
oodvm.SalesHeader[0]
oodvm.SalesPersonPurchasers[0]
//...

代表您想要的第一个订单。你可以使用它来迭代你想要的。

答案 1 :(得分:0)

您的视图模型只有您的订单(Sales_Line)的单个实体。你需要把它列为一个清单。

  public class Ordre_Open_Details_VM
    {
        public Sales_Header SalesHeader { get; set; }
        public List<Sales_Line> SalesLine { get; set; }
        public Purchase_Line PurchaseLine { get; set; }
        public Salesperson_Purchasers SalesPersonPurchasers { get; set; }
        public Sales_Comment_Line SalesCommentLine { get; set; }
    }

填充视图模型的代码仅调用自您使用FirstOrDefault以来找到的第一个项目。

要返回许多SalesLines,请使用Where&amp; ToList

oodvm.SalesLine = data_2.Sales_Line.Where(n => n.Document_No_ == id).ToList();

然后您的视图需要使用razor语法迭代列表,例如:

@foreach(var saleLine in Model.SalesLine)
{
  <div>@saleLine.PropertyXYZ</div>

}

作为奖励,您可以考虑更改代码以调用数据以提高效率。您使用您的代码调用数据库五次:

oodvm.SalesLine = data_2.Sales_Line.SelectMany(n => n.Document_No_ == id);
oodvm.SalesHeader = data_2.Sales_Header.SelectMany(m => m.No_ == oodvm.SalesLine.Document_No_);
oodvm.SalesPersonPurchasers = data_2.Salesperson_Purchasers.SelectMany(h=>h.Code == oodvm.SalesHeader.Salesperson_Code);
oodvm.SalesCommentLine = data_2.Sales_Comment_Line.SelectMany(z => z.No_ == oodvm.SalesLine.Document_No_);
oodvm.PurchaseLine = data_2.Purchase_Line.SelectMany(t=>t.Document_No_ == oodvm.SalesLine.Købsordrenr_);

每一行都告诉EF在另一个呼叫中返回数据库,并使用前一次呼叫的受限信息。在这种情况下,您可以创建一个实际上将在一次调用中执行此操作的查询。下面是将SalesLine调用和SalesHeader调用转换为一个数据库调用的示例。

oodvm.SalesLine = data_2.Sales_Line.FirstOrDefault(n => n.Document_No_ == id);
    oodvm.SalesHeader = data_2.Sales_Header.FirstOrDefault(m => m.No_ == oodvm.SalesLine.Document_No_);

更改为:

oodvm.SalesLine = data_2.Sales_Line.Include(n=>n.SalesHeader).Where(n=> n.Document_No_ == id).ToList();

由于SalesLine与SalesHeader相关,因此EF知道如何根据定义的关系检索它。

上面的示例使用了一种名为eager loading的技术。我告诉EF使用Include操作来一起获取相关的SalesHeader信息。在普通的SQL语法中,这就像:

    select * from SalesLine 
    Inner Join SalesHeader on SalesHeader.Document_No_ = SalesLine.Document_No_ 
where SalesLine.Document_No_ = id

实体框架也可以lazy load。我通常回避延迟加载,因此我的解决方案使用急切加载。

现在oodvm.SalesLine也将SalesLeader与SalesLine相关联,并且可以像oodvm.SalesLine[0].SalesHeader一样访问。

在上述情况下,每个SalesLine的SalesHeader将与EF代表您正常执行的SQL一样重复。如果您不希望视图模型中存在重复信息,则必须考虑使用EF中的Projection将查询结果转换为视图模型的SalesHeader单项,或者您可以在代码中将SalesHeader设置为SalesLines列表中的第一项,或者您可以在Razor中在循环上方的标题部分中执行相同的操作。

执行操作时的示例:

oodvm.SalesHeader = oodvm.SalesLine [0] .SalesHeader;

Razor中的示例:

<div>
<p>Sales Header</p>
<span>@Model.SalesLine[0].SalesHeader.Property</span>
...
@foreach...

如果您在Action ...

中填充了SalesHeader
<div>
<p>Sales Header</p>
<span>@Model.SalesHeader.Property</span>
...
@foreach...

使用projection,您可以编写一个包含所有上述所需项目的查询,并将其投影到视图模型对象中。它可能看起来像:

    oodvm = data_2.Sales_Line.Include(n=>n.SalesHeader)
.Where(n=> n.Document_No_ == id)
.Select(n=> new Ordre_Open_Details_VM {
      Sales_Header = n.SalesHeader.FirstOrDefault(),
      SalesLine = n
    }).ToList();

以上几行只是说明你会做什么。查找投影以获得更多指导。