请看下面的句子:
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上下文中填充这些Dtos。我想用标准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子句。我尝试使用extention方法做到这一点,但在使用基类(Address和Flags)和使用Interfaces时都失败了,因为IQuerable不能从Interface转换为Concrete类。
我有什么方法可以做到这一点吗?
最好的方法是使用这样的扩展方法:
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;没有做演员。
答案 0 :(得分:3)
您可以按如下方式实现扩展方法,并将泛型参数的约束设置为类型IAddress
和class
(这可以避免异常“LINQ to Entities仅支持转换EDM原语或枚举类型“)并在类型Company
,Animal
和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
。
答案 1 :(得分: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();