2012-06-15 103 views
3

设置一般属性我有一个看起来像这样多个查询:如何使用LINQ选择

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都从具有IdNameShortName性质的公共基类派生。 EntityASmallEntityBSmall也一样。我有很多看起来像这样的查询,所以我想做一些简写查询,首先将常见的东西排除在外。我发现了一个有点前途的扩展方法,看起来像这样:

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到SQL的表达式。看起来像AsEnumerable()把它收集在本地的地方它的全部工作。对于长篇大论的文章感到抱歉,但是有没有什么表达式方法可以用来编写可以与LINQ-to-SQL和Entity Framework一起使用的表达式?提前致谢。

+0

'EntityAs'是'IQueryable <>'? –

+0

难道你不能写一个泛型方法'ProjectOntoSmall',它需要一个'TEntity'类型的参数并将其转换为'TEntitySmall'?如果你对这些类型参数施加约束,而这些参数必须从基类型中派生出来,那我想可能会起作用。 –

回答

0

你想出的扩展方法看起来不错。

它只是你必须为每个派生实体创建它,这可能是罚款,因为你似乎有几个dervied实体。

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

所以,你的扩展方法是这样的

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; 

}

然后你就可以使用extesion方法如下为好。

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

这将消除您使用AsEnumerable的使用。 您还可以从你的基地转变为derviced方法用同样的方法,如果你想这样的:

DerivceEntityObject SetCommonProperties(BaseEntity) 

我希望这给你一个想法是什么我想在这里建议。

+0

Hm,适用于LINQ-to-SQL,但不适用于EF。它抱怨SetCommonProperties不能被转换为SQL。林猜测它适用于LINQ到SQL,因为LINQ-to-SQL和LINQ-to-Objects之间的线条更加模糊。 – Ocelot20

+0

是的,我同意我错过了EF的东西。它会抱怨,因为它试图翻译SQL中的方法。在这种情况下,你可以做的是删除这个keywork(没有更多的扩展方法),并以我提到的相同方式将它用作一个常规方法。 – Tabish

+0

例如:对于一个EntityAs选择SetCommonProperties(一个实体),然后照顾你正在做的事情。 – Tabish

1

你想让自己的代码变得干干净净,这总是很好用。也许你会用一些劳动和劳动以及一些巫术工作,但也许你会喜欢这个链接:Stop using AutoMapper in your Data Access Code。 (即使你不使用AutoMapper)。

通过这个漂亮的作品,你就可以编写简洁的语句,如:

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

我这次真的用我自己和我喜欢它。

+0

尼斯链接。我喜欢它,但不幸的是它对任何东西都没有帮助,只是非常简单的映射。我需要一些更强大的东西。 – Ocelot20