1

看下面的情景:

 class CompanyDto  {
     public string Street { get; set;}
     public int Number { get; set;}
     public bool IsAttr1 { get; set;}
     public bool IsAttr2 { get; set;}
     public bool IsAttr3 { get; set;}
     // Other not common Properties
 }

 class AnimalDto {
     public string Street { get; set;}
     public int Number { get; set;}
     // Other not common Properties
 }

 class HouseDto {
     public bool IsAttr1 { get; set;}
     public bool IsAttr2 { get; set;}
     public bool IsAttr3 { get; set;}
     // Other not common Properties
 }

 class PersonDto {
     public string Street { get; set;}
     public int Number { get; set;}
     public bool IsAttr1 { get; set;}
     public bool IsAttr2 { get; set;}
     public bool IsAttr3 { get; set;}
     // Other not common Properties
 }

我有这些要从 Entinty Framework 上下文中填充的 Dto。事情是我想使用标准 where 子句过滤结果。例子:

 List<PersonDto> prs = context.Person.Where(x => x.Number == SomeValue && Street == SomeOtherValue).Where( x=> x.IsAttr1 || x.IsAttr2).Select(//projection here).ToList();

 List<AnimalDto> anmls = context.Animal.Where(x => x.Number == SomeValue && Street == SomeOtherValue).Select(//projection here).ToList();

 etc.

我想将它们投影到 Dtos(简单),但我不想一次又一次地编写 Where 子句。我尝试使用扩展方法来做到这一点,但是在使用基类(地址和标志)和使用接口时都失败了,因为 IQuerable 不能从接口转换为具体类。

有什么办法可以做到这一点吗?

最好的方法是使用这样的扩展方法:

public static IQueryable<IAddress> WhereAddress(this IQueryable<IAddress> qry, int SomeValue, int SomeOtherValue)
    {
        return qry.Where(x => x.Number == SomeValue && Street == SomeOtherValue);
    }

但是我不能在 WhereAddress 子句和 IQuerable.cast(); 之后添加 WhereFlags;没有做演员。

4

2 回答 2

3

您可以通过将泛型参数约束为类型IAddressclass这避免了“LINQ to Entities 仅支持强制转换 EDM 基元或枚举类型”异常)来实现扩展方法,并在您的类型上实现接口CompanyAnimal并且Person

public static IQueryable<TAddress> WhereAddress<TAddress>(this IQueryable<TAddress> qry, int SomeValue, string SomeOtherValue)
  where TAddress : class, IAddress {
    return qry.Where(x => x.Number == SomeValue && x.Street == SomeOtherValue);
}

有了这个你可以打电话

context.Person.WhereAddress(SomeValue,SomeOtherValue).Where(x=> x.IsAttr1 || x.IsAttr2);

但不是

context.House.WhereAddress(SomeValue,SomeOtherValue);

原因House没有执行IAddress

于 2013-10-02T09:19:51.060 回答
1

怎么样:

public IQueryable<T> GetByAddress<T>(DbContext context, int number, string street)
{
    return context.Set<T>().Select<T, IAddress>(x => x.Number == SomeValue && x.Street == SomeOtherValue);  
}

然后在外部你应该能够做到

List<PersonDto> prs = GetByAddress<Person>(context, 1, "1234 Street")
                          .Select(...)
                          .ToList();
List<AnimalDto> anmls = GetByAddress<Animal>(context, 2, "5678 Road")
                          .Select(...)
                          .ToList();

如果您更喜欢扩展方法方法,那么您应该能够做到这一点,它现在不起作用的原因是因为您没有将表格投影到IAddress. LINQ 不支持隐式转换,例如

List<PersonDto> prs = context.Person.Select<Person, IAddress>()
                                    .WhereAddress(1, "1234 Street")
                                    .Select(...)
                                    .ToList();
List<PersonDto> prs = context.Animal.Select<Animal, IAddress>()
                                    .WhereAddress(2, "5678 Street")
                                    .Select(...)
                                    .ToList();
于 2013-10-02T10:17:26.523 回答