gpt4 book ai didi

c# - 避免 Linq-To-Objects 但允许重新利用代码

转载 作者:太空宇宙 更新时间:2023-11-03 10:46:16 25 4
gpt4 key购买 nike

想象一下这三个 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);
}

它的问题是要使用方法 AsJson() 需要 ToList() ...内存


在下面的方法中,我们称之为方法(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)

或者它不会? (保留其余代码不变)

最佳答案

您的问题的起点是实体类中的这些 AsJson() 方法。但那是我一开始就不会做的事情。首先,它在您的领域中引入了传输概念,其次,实体的表示可能取决于用例:也许在其他情况下,您只想展示没有乐器的音乐家。

如果您想将实体序列化为 JSON,您通常需要禁用代理生成,这会禁用延迟加载并具体化原始实体类型...

db.ProxyCreationEnabled = false;

...并急切地加载您想要返回的所有内容...

MusicBand g = db.MusicBands
.Include(mb => mb.Members.Select(m => m.Instrument))
.SingleOrDefault(mb => mb.MusicBandId == musicBandId);

...并以 JSON 格式返回 g

这在一个 SQL 查询中完成了工作。在您的备选方案中,总会有至少两个查询,因为您首先获取 MusicBand,然后通过延迟加载获取成员(和乐器)。

如果你想序列化实体的其他表示,你应该映射到 DTO(或 View 模型)对象。在这里,像 AutoMapper 这样的工具就派上用场了。

关于c# - 避免 Linq-To-Objects 但允许重新利用代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23284680/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com