Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 避免Linq到对象,但允许代码的重用_C#_Entity Framework_Linq To Entities_Linq To Objects_Code Reuse - Fatal编程技术网

C# 避免Linq到对象,但允许代码的重用

C# 避免Linq到对象,但允许代码的重用,c#,entity-framework,linq-to-entities,linq-to-objects,code-reuse,C#,Entity Framework,Linq To Entities,Linq To Objects,Code Reuse,想象一下这三个EF类 class Instrument { public long InstrumentId { get; set; } public string Model { get; set; } public dynamic AsJson() { return new { instrumentId = this.Instru

想象一下这三个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; }
    }
它的问题是要使用方法
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)的优点, 重复利用且无性能问题

我想听听有很多导航属性的大型系统是如何实现这一点的。
当需要不同的JSON(共享子部分)时,它们如何设法减少耦合

还有一个子问题:
在方法(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);
…并将
g
作为JSON返回

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


如果要序列化实体的其他表示形式,则应映射到DTO(或视图模型)对象。这里有一个像AutoMapper这样的工具很方便。

您更关注我的性能问题,这是我关注的50%。另外50%是再利用,这就是我被卡住的地方。如果我需要在每个不同的查询中填充这些DTO,这些DTO将如何帮助我实现这一点?使用AutoMapper,这可能是一个简单的语句,如
Mapper.Map(g)
。你可以在一个单独的查询中添加它,当然,你也可以使用一个服务来公开查询,并映射到不同的DTO,例如在控制器中。AutoMapper还可以在一个简短的语句中将
IQueryable
直接投影到DTO对象列表中。我将看一看AutoMapper,并将你的答案标记为正确答案(AutoMapper)如果DTO中的集合名称具有相同的名称(或者您可以配置源集合和目标集合),则AM还将映射嵌套集合。它确实是摆脱所有这些嵌套的
selectnew{}
语句的工具。
MusicBand g = db.MusicBands
                .Include(mb => mb.Members.Select(m => m.Instrument))
                .SingleOrDefault(mb => mb.MusicBandId == musicBandId);