3

我有多个查询,如下所示:

var query = from a in EntityAs
            select new EntityASmall()
            {
                // Common Stuff:
                Id = a.Id,
                Name = a.Name,
                ShortName = a.ShortName,
                // Specific to EntityA:
                ASpecificProperty1 = a.1,
                ASpecificProperty2 = a.2
            };

var query = from b in EntityBs
            select new EntityBSmall()
            {
                // Common Stuff:
                Id = b.Id,
                Name = b.Name,
                ShortName = b.ShortName,
                // Specific to EntityB:
                BSpecificProperty1 = b.1,
                BSpecificProperty2 = b.2
            };

EntityA 和 EntityB 都派生自具有 、 和 属性的公共IdNameShortNameEntityASmall和 也是如此EntityBSmall。我有很多看起来像这样的查询,所以我想做一些速记查询,先把常见的东西排除在外。我发现了一个有点前途的扩展方法,看起来像这样:

public static TSource SetCommonProperties<TSource>(this TSource input, EntityBaseClass entity, Action<TSource> updater) where TSource : EntitySmallBase
{
    input.Id = entity.Id;
    input.Name = entity.Name;
    input.ShortName = entity.Name;

    updater(input);

    return input;
}

我可以这样使用它:

var query = from a in EntityAs.AsEnumerable()
            select new EntityASmall().SetCommonProperties(a, x =>
            {
                ASpecificProperty1 = x.1;
                ASpecificProperty2 = x.2;
            });

注意AsEnumerable(). 没有它,我会得到“无法将带有语句体的 lambda 表达式转换为表达式树”,我大致猜测这意味着它正在尝试将Action部分转换为 LINQ-to-SQL 的表达式。看起来AsEnumerable()将集合在本地完全发挥作用。很抱歉这篇冗长的帖子,但是有没有任何表达方式来编写这个可以与 LINQ-to-SQL 和实体框架一起使用的方法?提前致谢。

4

2 回答 2

1

您想让您的代码 DRY,这总是需要付出一些努力。也许您会通过一些辛勤劳动和一些Expression巫术来使您的方法工作,但也许您会喜欢这个链接:停止使用 AutoMapper in您的数据访问代码。(即使您不使用 AutoMapper)。

通过这项出色的工作,您将能够编写简洁的语句,例如:

context.EntityAs.Project().To<EntityASmall>();
context.EntityBs.Project().To<EntityBSmall>();

我自己用过这个,我真的很喜欢它。

于 2012-06-16T21:17:12.570 回答
0

您提出的扩展方法看起来不错。

它只是你必须为每个派生实体创建它,这在你的情况下可能很好,因为你似乎有几个派生实体。

其次,我不认为你真的需要在你的扩展方法中传递那个动作委托。如果可能的话,只需在其中调用该方法即可。我对设计了解不多。

所以你的扩展方法看起来像这样

public static TSource SetCommonProperties<TSource>(this TSource input, EntityBaseClass entity)     where TSource : EntitySmallBase 
{ 
   input.Id = entity.Id; 
   input.Name = entity.Name; 
   input.ShortName = entity.Name; 

   this.Update(input); // Or this method could exist in any other class or static class.

  return input; 

}

然后你也可以使用如下的扩展方法。

var query = from a in EntityAs
        select new EntityASmall
        {      
            ASpecificProperty1      
            ASpecificProperty2    
        }).SetCommonProperties(a,entity)    

这将消除您对 AsEnumerable 的使用。如果需要,您还可以使用相同的方法从基础方法转换为 derviced 方法:

DerivceEntityObject SetCommonProperties(BaseEntity)

我希望这能让您了解我在这里要提出的建议。

于 2012-06-15T16:12:17.737 回答