【发布时间】:2014-04-25 05:16:52
【问题描述】:
想象一下这三个 EF 类
class Instrument
{
public long InstrumentId { get; set; }
public string Model { get; set; }
public dynamic AsJson()
{
return new
{
instrumentId = this.InstrumentId,
model = this.Model
}
}
}
class Musician
{
public long MusicianId { get; set; }
public virtual Instrument Instrument { get; set; } // notice navigation
public string Name { get; set; }
public dynamic AsJson()
{
return new
{
musicianId = this.MusicianId,
name = this.Name,
instrument = this.Instrument.AsJson()
}
}
}
class MusicBand
{
public long MusicBandId { get; set; }
public string Name { get; set; }
public virtual List<Musician> Members { get; set; }
}
现在想象一下,我们需要返回 JSON 的多个彼此相似的操作。
让我们称之为方法(A)
// ajax/Bands/Members
//
public JsonResult Members(long musicBandId)
{
MusicBand g = db.MusicBands.SingleOrDefault(g => g.MusicBandId == musicBandId);
if (g == null)
return null;
return Json(new
{
error = false,
message = "",
members = from p in g.Members.ToList() select p.AsJson()
}, JsonRequestBehavior.AllowGet);
}
它的问题是 ToList() 是使用方法 AsJson() 所必需的......所以在内存中完成了大量工作
在下面的方法中,我们称之为方法(B),这不是问题。在内存中完成的工作是最少的,大部分工作都是在SQL中完成的。事实上,它是一个包含所有需要的大型 SQL 查询。
// ajax/Bands/Members
//
public JsonResult Members(long musicBandId)
{
MusicBand g = db.MusicBands.SingleOrDefault(g => g.MusicBandId == musicBandId);
if (g == null)
return null;
return Json(new
{
error = false,
message = "",
persons = from p in g.Members select new
{
musicianId = p.MusicianId,
name = p.Name,
instrument = select new
{
instrumentId = instrument.InstrumentId,
model = instrument.Model
}
}
}, JsonRequestBehavior.AllowGet);
}
方法 A.
优点:整洁的代码,我可以在其他操作中重用代码,减少耦合
缺点:性能问题(在内存中完成的工作!)
方法 B:
优点:丑陋的代码,如果其他操作需要类似的东西,我最终会复制粘贴代码!这带来了耦合(多次修改类似的代码)
缺点:没有性能问题(使用 SQL 完成工作!)
最后,问题: 我正在寻找另一种方法(C),它具有更好的(A)和(B), 重复利用且无性能问题
我想知道具有许多导航属性的大型系统是如何实现这一目标的。
当需要不同的 JSONS(共享子部分)时,他们如何设法减少耦合
还有一个子问题:
在方法 (A) 中,以下内容会有所不同吗?
db.MusicBands.Include(g => g.Members.Select(m => m.Instrument)).SingleOrDefault(g => g.MusicBandId == musicBandId)
还是不会? (保持其余代码不变)
【问题讨论】:
标签: c# entity-framework linq-to-entities linq-to-objects code-reuse