DB First,MVC4,Entity Framework 5 – 显示来自多个表的值的最佳实践?
DB First, MVC4, Entity Framework 5 – best practice to display values from multiple tables?
首先,我是 DB First、MVC4、Entity Framework5 尤其是 LINQ 的新手。
假设我们有一个包含下表的数据库:
T_Project
- string ProjectNumber (PK)
T_NetworkIpAddress
- string IP (PK)
- …some more attributes…
T_Unit
- Int UnitId (PK)
- string ProjectNumber (FK)
- string IpAddress (FK)
- … some more attributes…
T_ProjectAndIpIntersection
- string ProjectNumber (PK,FK)
- string IpAddress (PK,FK)
现在我们要创建一个 ProjectNumberResultView
,我们可以在其中搜索 ProjectNumber
。结果应显示每个 ProjectNumber
,其中包含给定的 searchString
和其他表中的一些附加数据。
我的解决方案是创建一个新的 ViewModel class:
public class ProjectNumberSearchResult
{
public ProjectNumberSearchResult () {}
public string ProjectNumber { get; set; }
public string UnitId { get; set; }
public string IpAddress { get; set; }
}
我为我的SearchController
写了这个方法:
public ActionResult ProjectNumberResultView(string searchString)
{
ViewBag.InputSearchString = searchString;
List<ProjectNumberSearchResult> results = new List<ProjectNumberSearchResult<>();
if (!String.IsNullOrEmpty(searchString))
{
searchString = searchString.Trim();
//find projects
var projects = from p in db.T_ProjectNumber
select p;
projects = projects.Where(s => s.ProjectNumber.Contains(searchString));
var units = from u in db.T_Unit
select u;
foreach (var p in projects.ToList())
{
var pUnits = units.Where(u => u.ProjectNumber.Equals(p.ProjectNumber));
//add only project number when there are no unit entries
if (pUnits.Count() == 0)
results.Add(new ProjectNumberSearchResult () { ProjectNumber = p.ProjectNumber });
//else add object with additional unit data for every unit entry
foreach (var unit in pUnits)
{
var result = new ProjectNumberSearchResult();
result.ProjectNumber = p.ProjectNumber;
result.UnitId = unit.UnitId;
result.IpAddress = unit.IpAddress;
results.Add(result);
}
}
}
return View(results);
}
我讨厌这个解决方案,因为我必须使用两个 foreach 迭代......我当然更喜欢 join 解决方案,但我无法解决。
我试过这样的事情:
var projects = from p in db.T_ProjectNumber
select p;
projects = projects.Where(s => s.ProjectNumber.Contains(searchString));
var units = from u in db.T_Unit
select u;
//find all projects with or without (there are project number without units) units incl. their additional data
var results = projects.Join(units,
pNumber => pNumber.ProjectNumber,
unitPNumber => unitPNumber.ProjectNumber,
(pNumber, unitPNumber) => new { T_ProjectNumber = pNumber,
T_Unit = unitPNumber })//.Select(??)
//return View(??)
我的问题是:
- 什么是正确的 (LINQ??) select 语法?
- 因为它是一个合并的对象,我应该 return 做什么?
或者我必须在我的 ProjectNumberResultView.cshtml 文件中添加什么?
- 有没有更好的方法?
您可以将 LINQ 查询投影到 IEnumerable<ProjectNumberSearchResult>
:
var results = projects
.Join(
units,
project => project.ProjectNumber,
unit => unit.ProjectNumber,
(project, unit) => new ProjectNumberSearchResult
{
ProjectNumber = project.ProjectNumber,
UnitId = unit.UnitId,
// you can populate any other properties from
// the view model that you need
})
.ToList();
你的视图当然会强类型化到视图模型:
@model IEnumerable<ProjectNumberSearchResult>
'all in one'怎么样?:
List<MyViewModel> projects =
(from p in db.T_ProjectNumber
join u in db.unit on p.ProjectNumber equals u.ProjectNumber
where p.ProjectNumber.Contains(searchString)
select new MyViewModel()
{
MyViewModelProperty1 = p.ProjectNumber,
MyViewModelProperty2 = u.Stuff
// etc, etc
}).ToList();
return MyViewModel(仅包含视图所需属性的自定义对象)到视图。
我解决了这个问题,因为我要求一个解决方案,它还显示了没有单位的项目编号(左连接):
public ActionResult ProjectNumberResultView(string searchString)
{
ViewBag.InputSearchString = searchString;
IEnumerable<ProjectNumberSearchResult> results = new List<ProjectNumberSearchResult>();
if (!String.IsNullOrEmpty(searchString))
{
searchString= searchString.Trim();
results = (from p in db.T_ProjectNumber
from unit in db.T_Unit
.Where(unit => unit.ProjectNumber == p.ProjectNumber)
.DefaultIfEmpty()
where p.ProjectNumber.Contains(searchString)
select new ProjectNumberSearchResult
{
ProjectNumber = p.ProjectNumber,
UnitId = unit.UnitId,
IpAddress = unit.IpAddress
}
);
}
return View(results);
}
首先,我是 DB First、MVC4、Entity Framework5 尤其是 LINQ 的新手。
假设我们有一个包含下表的数据库:
T_Project
- string ProjectNumber (PK)
T_NetworkIpAddress
- string IP (PK)
- …some more attributes…
T_Unit
- Int UnitId (PK)
- string ProjectNumber (FK)
- string IpAddress (FK)
- … some more attributes…
T_ProjectAndIpIntersection
- string ProjectNumber (PK,FK)
- string IpAddress (PK,FK)
现在我们要创建一个 ProjectNumberResultView
,我们可以在其中搜索 ProjectNumber
。结果应显示每个 ProjectNumber
,其中包含给定的 searchString
和其他表中的一些附加数据。
我的解决方案是创建一个新的 ViewModel class:
public class ProjectNumberSearchResult
{
public ProjectNumberSearchResult () {}
public string ProjectNumber { get; set; }
public string UnitId { get; set; }
public string IpAddress { get; set; }
}
我为我的SearchController
写了这个方法:
public ActionResult ProjectNumberResultView(string searchString)
{
ViewBag.InputSearchString = searchString;
List<ProjectNumberSearchResult> results = new List<ProjectNumberSearchResult<>();
if (!String.IsNullOrEmpty(searchString))
{
searchString = searchString.Trim();
//find projects
var projects = from p in db.T_ProjectNumber
select p;
projects = projects.Where(s => s.ProjectNumber.Contains(searchString));
var units = from u in db.T_Unit
select u;
foreach (var p in projects.ToList())
{
var pUnits = units.Where(u => u.ProjectNumber.Equals(p.ProjectNumber));
//add only project number when there are no unit entries
if (pUnits.Count() == 0)
results.Add(new ProjectNumberSearchResult () { ProjectNumber = p.ProjectNumber });
//else add object with additional unit data for every unit entry
foreach (var unit in pUnits)
{
var result = new ProjectNumberSearchResult();
result.ProjectNumber = p.ProjectNumber;
result.UnitId = unit.UnitId;
result.IpAddress = unit.IpAddress;
results.Add(result);
}
}
}
return View(results);
}
我讨厌这个解决方案,因为我必须使用两个 foreach 迭代......我当然更喜欢 join 解决方案,但我无法解决。
我试过这样的事情:
var projects = from p in db.T_ProjectNumber
select p;
projects = projects.Where(s => s.ProjectNumber.Contains(searchString));
var units = from u in db.T_Unit
select u;
//find all projects with or without (there are project number without units) units incl. their additional data
var results = projects.Join(units,
pNumber => pNumber.ProjectNumber,
unitPNumber => unitPNumber.ProjectNumber,
(pNumber, unitPNumber) => new { T_ProjectNumber = pNumber,
T_Unit = unitPNumber })//.Select(??)
//return View(??)
我的问题是:
- 什么是正确的 (LINQ??) select 语法?
- 因为它是一个合并的对象,我应该 return 做什么? 或者我必须在我的 ProjectNumberResultView.cshtml 文件中添加什么?
- 有没有更好的方法?
您可以将 LINQ 查询投影到 IEnumerable<ProjectNumberSearchResult>
:
var results = projects
.Join(
units,
project => project.ProjectNumber,
unit => unit.ProjectNumber,
(project, unit) => new ProjectNumberSearchResult
{
ProjectNumber = project.ProjectNumber,
UnitId = unit.UnitId,
// you can populate any other properties from
// the view model that you need
})
.ToList();
你的视图当然会强类型化到视图模型:
@model IEnumerable<ProjectNumberSearchResult>
'all in one'怎么样?:
List<MyViewModel> projects =
(from p in db.T_ProjectNumber
join u in db.unit on p.ProjectNumber equals u.ProjectNumber
where p.ProjectNumber.Contains(searchString)
select new MyViewModel()
{
MyViewModelProperty1 = p.ProjectNumber,
MyViewModelProperty2 = u.Stuff
// etc, etc
}).ToList();
return MyViewModel(仅包含视图所需属性的自定义对象)到视图。
我解决了这个问题,因为我要求一个解决方案,它还显示了没有单位的项目编号(左连接):
public ActionResult ProjectNumberResultView(string searchString)
{
ViewBag.InputSearchString = searchString;
IEnumerable<ProjectNumberSearchResult> results = new List<ProjectNumberSearchResult>();
if (!String.IsNullOrEmpty(searchString))
{
searchString= searchString.Trim();
results = (from p in db.T_ProjectNumber
from unit in db.T_Unit
.Where(unit => unit.ProjectNumber == p.ProjectNumber)
.DefaultIfEmpty()
where p.ProjectNumber.Contains(searchString)
select new ProjectNumberSearchResult
{
ProjectNumber = p.ProjectNumber,
UnitId = unit.UnitId,
IpAddress = unit.IpAddress
}
);
}
return View(results);
}