我在SQL方面经验丰富,在LINQ和OOP方面经验不足,结果对LINQ感到非常沮丧,所以请耐心等待。
我正在按照下面的标签使用MVC / Entity Framework。
我有两张桌子。一个名为Header
的表绑定到网格。当我创建一个记录
要插入到此Header
表中,我需要查找一些匹配的相关Detail
记录并汇总并在网格中显示它们。
我现在将此限制在LINQ方面。
例如,我有这些详细记录:
Date Segment Location Amount1 Amount2
2013-12-01 ABC ZZ 12 2
2013-12-02 ABC ZZ 50 3
2013-12-03 ABC ZZ 2 4
2013-12-01 DEF ZZ 7 5
我在网格中创建了这个标题记录:
DateFrom DateTo Segment Location DetailAmount1 DetailAmount2
2013-12-01 2013-12-07 ABC ZZ ( to be populated )
DetailAmount1应为64,DetailAmount2应为9
所以我的视图调用控制器中的Grid_Create
操作来获取一个带有所需数据的视图模型(除了我的汇总详细信息值和数据库生成的密钥之外什么都没有)
这是我的控制者:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Grid_Create(
[DataSourceRequest]DataSourceRequest request,
[Bind(Prefix = "models")]IEnumerable<Header_ViewModel> objects,
string Location,
int? Segment_ID,
DateTime? Start_Date,
DateTime? End_Date)
{
using (var MyDB = new DBEntities())
{
// Keep the inserted entitites here.
// Used to return the result later.
var entities = new List<Header_Table>();
if (ModelState.IsValid)
{
foreach (var obj in objects)
{
// PART A: Summarise estimates out of Detail
var est =
(from e in MyDB.Detail_Table
where e.SRC_System == Location
where e.Segment_ID == Segment_ID
where e.Transaction_Date >= Start_Date
where e.Transaction_Date <= End_Date
group e by e.Segment_ID into e
select
new Header_ViewModel
{
Amount1 = e.Sum(x => x.Amount1),
Amount2 = e.Sum(x => x.Amount2),
Amount3 = e.Sum(x => x.Amount3),
Amount4 = e.Sum(x => x.Amount4),
Amount5 = e.Sum(x => x.Amount5),
Amount6 = e.Sum(x => x.Amount6)
})
.FirstOrDefault();
// PART B: If there are no estimates, generate a 0
if (est == null)
{
est = new Header_ViewModel
{
Amount1 = 0,
Amount2 = 0,
Amount3 = 0,
Amount4 = 0,
Amount5 = 0,
Amount6 = 0
};
}
// PART C: Create a new entity
// and set its properties from the posted model
var entity = new Header_Table
{
Transaction_ID = obj.Transaction_ID,
Value1 = obj.Value1,
Value2 = obj.Value2,
Value3 = obj.Value3,
// Summary from detail table
Amount2 = est.Amount2,// obj.Amount2,
Amount3 = est.Amount3, // obj.Amount3,
Amount1 = est.Amount1,// obj.Amount1,
Amount4 = est.Amount4, //obj.Amount4,
Amount5 = est.Amount5, // obj.Amount5,
Amount6 = est.Amount6, // obj.Amount6,
Location = Location,
Segment_ID = Segment_ID,
Start_Date = Start_Date,
End_Date = End_Date,
// assign default values
Updated_By = User.Identity.Name,
Updated_Date = DateTime.Now
};
// Add the entity
MyDB.Header_Table.Add(entity);
// Store the entity for later use
entities.Add(entity);
}
// Insert the entities in the database
MyDB.SaveChanges();
}
// Return the inserted entities. Also return any validation errors.
return Json(
entities.ToDataSourceResult(
request,
ModelState, obj => new Header_ViewModel
{
Transaction_ID = obj.Transaction_ID,
Amount2 = obj.Amount2,
Value1 = obj.Value1,
Amount3 = obj.Amount3,
Amount1 = obj.Amount1
}));
}
}
问题:
找不到详细记录。什么是将est
对象默认为单个零项的好方法?目前在 B部分中我正在检查est==null
并手动加载它。如何让FirstOrDefault自动为我做这个? (因此删除 B部分)。我相信我应该能够传入一个类型,但是我无法使语法正确,即如果我从B部分的new
中获取所有内容并将其作为参数放入FirstOrDefault我得到System.Linq.IQueryable<Header_ViewModel> does not contain a definition for 'FirstOrDefault...
在 A部分中获取摘要时,我实际上不需要按Segment_ID
分组,我只需要该表的总摘要。然而,似乎我必须分组以获得LINQ中的聚合。我看过e.GetType()
提及小组的其他帖子,但我收到错误LINQ to Entities does not recognize the method 'System.Type GetType()'.....
。
鉴于这是一条新记录,我是否可以直接从entity
填充MyDB.Detail_Table
(从而合并A和C部分)?我试过这个,但每次都有错误。抱歉没有发布确切的错误,但如果有人认为有可能我会再次尝试并发布错误。
答案 0 :(得分:0)
问题1 我能想到的最简单的解决方案是(使用您的代码作为基础):
var est =
(from e in MyDB.Detail_Table
where e.SRC_System == Location
where e.Segment_ID == Segment_ID
where e.Transaction_Date >= Start_Date
where e.Transaction_Date <= End_Date
group e by e.Segment_ID into e
select
new Header_ViewModel
{
Amount1 = e.Sum(x => x.Amount1),
Amount2 = e.Sum(x => x.Amount2),
Amount3 = e.Sum(x => x.Amount3),
Amount4 = e.Sum(x => x.Amount4),
Amount5 = e.Sum(x => x.Amount5),
Amount6 = e.Sum(x => x.Amount6)
})
.FirstOrDefault() ?? new Header_ViewModel();
问题2 嗯,是的......在这里做的不多,使用常数是可能的,如here所述。这似乎有效:
var est =
MyDB.DetailTableSet.Where(e => e.SRC_System == Location && e.Segment_ID == Segment_ID
&& e.Transaction_Date >= Start_Date && e.Transaction_Date <= End_Date)
.GroupBy(e => 1)
.Select(e => new Header_ViewModel
{
Amount1 = e.Sum(x => x.Amount1),
Amount2 = e.Sum(x => x.Amount2),
})
.SingleOrDefault() ?? new Header_ViewModel();
问题3 没有好办法做到这一点。解释原因和一些解决方法here,但在你的情况下,我不会走得那么远。这就是我要去的地方:
var est =
MyDB.DetailTableSet.Where(e => e.SRC_System == Location && e.Segment_ID == Segment_ID
&& e.Transaction_Date >= Start_Date && e.Transaction_Date <= End_Date)
.GroupBy(e => 1)
.Select(e => new Header_ViewModel
{
Amount1 = e.Sum(x => x.Amount1),
Amount2 = e.Sum(x => x.Amount2),
})
.SingleOrDefault() ?? new Header_ViewModel();
var entity = new HeaderTable()
{
Transaction_ID = obj.Transaction_ID,
Value1 = obj.Value1,
Value2 = obj.Value2,
Value3 = obj.Value3,
// Summary from detail table
Amount1 = est.Amount1,
Amount2 = est.Amount2,
Location = Location,
Segment_ID = Segment_ID,
Start_Date = Start_Date,
End_Date = End_Date,
// assign default values
Updated_By = "Myself",
Updated_Date = DateTime.Now
};
// Add the entity
MyDB.HeaderTableSet.Add(entity);
// Store the entity for later use
entities.Add(entity);