繁体   English   中英

实体框架的对象的Linq set属性无需SELECT进行额外投影

[英]Entity Framework Linq set property of an object without additional projection by SELECT

我正在使用Entity Framework 6实现继承方案。继承仅在DTO级别存在,即,我有两个类FooBar : Foo ,我有第一个方法选择一个IQueryable<Foo> ,然后有几个方法选择用于特定的继承类(如Bar)。

通常,我会有类似的代码

from foo in SelectFoo()
join barAdditionalProps in .....    
select new Bar{
    Id = foo.Id,
    Description = foo.Description,
    Baz = barAdditionalProps.Baz}

结果将提供一个不错的单个SQL查询。

不幸的是,这意味着必须在第二次投影期间复制foo的所有属性(第一个投影在SelectFoo内部)。 在现实生活中,这意味着使用SelectFoo在每种方法中复制20多个属性。

我想做这样的事情(代码是在LINQPad中编写的,假设this == EFContext):

void Main()
{      
    (from barBase in SelectT<Bar>()
     join field in this.Fields on barBase.Id equals field.ProductId
     let _1 = barBase.Baz = field.Baz // this part fails with exception
                                      // An expression tree may not contain an assigment operator         
     select barBase)
    .First()
    .Dump();      
}

public IQueryable<T> SelectT<T>() where T : Foo, new() 
{
    return this
           .Products
           .Select(x => new T
           {
                 Id = x.Id,
                 Description = x.Description
           });
}

public class Foo
{
    public string Description {get;set;}
    public int Id {get;set;}
}

public class Bar : Foo
{
    public int Baz {get;set;}
}

收到上述异常后,我正在寻找一种方法来完成这项工作,或寻求任何其他解决方案使我无法在第二次投影时复制所有基类属性。

由于没有可用的现有工具来完成这项工作,因此我编写了自己的库,该库使用表达式树修改自动将子类dto中的基类dto投影到项目中。

现在代替这个

     IQueryable<BaseDto> baseQuery = GetBaseQuery();

  IQueryable<SubclassDto> query = from baseDto in baseQuery
                                  let moreData = DataContext.vMoreData.FirstOrDefault(x => x.Id == baseDto.Id)
                                  select new SubclassDto()
                                  {
                                    NewProp1 = moreData.Foo,
                                    NewProp2 = moreData.Baz,
                                    OldProp1 = moreData.SomeOverridingData,

                                    OldProp2 = baseDto.OldProp2,
                                    OldProp3 = baseDto.OldProp3,
                                    OldProp4 = baseDto.OldProp4,
                                    //... 20 more projections from BaseDto to SubclassDto
                                  };

我们有这个

 IQueryable<BaseDto> baseQuery = GetBaseQuery();

 IQueryable<SubclassDto> query = from baseDto in baseQuery                                  
                                 let moreData = DataContext.vMoreData.FirstOrDefault(x => x.Id == baseDto.Id) 
                                 select baseDto.AutoProjectInto(() => new SubclassDto()
                                 {
                                  NewProp1 = moreData.Foo,
                                  NewProp2 = moreData.Baz,
                                  OldProp1 = moreData.SomeOverridingData
                                 });

 IQueryable<SubclassDto> activateQuery = query.ActivateAutoProjects(); 

并且不受SubclassDto初始化约束的所有属性都是从baseDto自动投影的。

可通过Github https://github.com/IKoshelev/Linq.AutoProject和NuGet https://www.nuget.org/packages/Linq.AutoProject获取库

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM