实体的动态 linq 以符合 DRY
dynamic linq to entities to comply with DRY
有没有办法动态地执行以下操作,这样我就不必重复自己了?
var result = from c in _Entities.Cars
where c.Colour == "White"
select c;
var result = from m in _Entities.Bikes
where m.Colour == "White"
select m;
etc...
如:
var entities = new List<string> {"Cars", "Bikes"};
foreach (var e in entities)
{
var result = from m in e //pseudo code
where m.Colour == "White"
select m;
}
如果 Cars 和 Bikes 实现一个公共接口,比如 IVehicle,它有颜色 属性,您可以定义一个函数:
public IEnumerable<IVehicle> GetWhiteVehicles(IEnumerable<IVehicle> vehicles) {
return vehicles.Where(p => p.Colour == "White");
}
然后
var result = GetWhiteVehicles(_Entities.Cars);
var result = GetWhiteVehicles(_Entities.Bikes);
如果汽车和自行车是从 Entity Framework 生成的 类,您仍然可以通过添加一个新的源文件来使它们实现一个接口,其中包含 类 的部分定义同名:
public partial class Bikes : IVehicle { }
public partial class Cars : IVehicle { }
这应该有效:
var entities = new List<List<dynamic>> {_Entities.Cars.ToList<dynamic>(), _Entitites.Bikes.ToList<dynamic>()};
foreach (var l in entities)
{
var result = from m in l
where m.Colour == "White"
select m;
}
因此您可以避免对您的业务模型进行任何更改。然而,因此 dynamic
类型仅在运行时解析,无法确保 属性 Colour
确实存在于该类型上。
添加一个包含颜色的界面(IColorful)。设置您的汽车和自行车以实现该接口。创建并调用函数:
List<IColorful> FindByColor(IEnumerable<IColorful> list, string color)
{
List<IColorful> result = list.Where(item => item.Color == color).ToList();
return result;
}
这样称呼它:
var entities = FindByColor(_Entities.Cars, color);
entities.AddRange(FindByColor(_Entities.Bikes, color))
首先要么定义它们都派生自的基 class,要么定义它们都实现的接口。我将从这里假设他们实现了一个 IColoured
接口和 Colour
属性。 (虽然我会注意到在成员名称中使用 en-US 很常见,因此颜色由 Color
属性 表示)。
所以,假设您的汽车 class 是由 EF 创建的:
namespace SomeNamespace
{
public partial class Cars
{
/*…*/
public string Colour { get; set; }
/*…*/
}
}
然后你可以有一个文件:
namespace SomeNamespace
{
public partial class Cars : IColoured
{
}
}
因为在编译 class 定义时将两个 partial
代码组合在一起,您的代码只需要指示接口已实现,匹配 属性 的事实在另一个文件无关紧要。
然后:
public static IQueryable<T> FilterByColour<T>(this IQueryable<T> source, string colour)
where T : IColoured
{
return source.Where(p => p.Colour == colour);
}
现在您可以使用 _Entities.Cars.FilterByColour("white")
、_Entities.Bikes.FilterByColour("blue")
等。如果按 "white"
过滤是一种特别常见的情况,那么:
重要提示:如果您没有充分的理由(例如使用不是与 EF 兼容),请使用 IQueryable<>
,以便它仍由 EF 处理,并且可以在数据库上进行过滤,而不是从数据库中检索所有内容并在您的应用程序中进行过滤。
public static IQueryable<T> FilterWhite<T>(this IQueryable<T> source)
where T : IColoured
{
return source.FilterByColour("white");
}
或者,如果 FilterByColour 没有其他用途,那么:
public static IQueryable<T> FilterWhite<T>(this IQueryable<T> source)
where T : IColoured
{
return source.Where(p => p.Colour == "white");
}
会起作用。
有没有办法动态地执行以下操作,这样我就不必重复自己了?
var result = from c in _Entities.Cars
where c.Colour == "White"
select c;
var result = from m in _Entities.Bikes
where m.Colour == "White"
select m;
etc...
如:
var entities = new List<string> {"Cars", "Bikes"};
foreach (var e in entities)
{
var result = from m in e //pseudo code
where m.Colour == "White"
select m;
}
如果 Cars 和 Bikes 实现一个公共接口,比如 IVehicle,它有颜色 属性,您可以定义一个函数:
public IEnumerable<IVehicle> GetWhiteVehicles(IEnumerable<IVehicle> vehicles) {
return vehicles.Where(p => p.Colour == "White");
}
然后
var result = GetWhiteVehicles(_Entities.Cars);
var result = GetWhiteVehicles(_Entities.Bikes);
如果汽车和自行车是从 Entity Framework 生成的 类,您仍然可以通过添加一个新的源文件来使它们实现一个接口,其中包含 类 的部分定义同名:
public partial class Bikes : IVehicle { }
public partial class Cars : IVehicle { }
这应该有效:
var entities = new List<List<dynamic>> {_Entities.Cars.ToList<dynamic>(), _Entitites.Bikes.ToList<dynamic>()};
foreach (var l in entities)
{
var result = from m in l
where m.Colour == "White"
select m;
}
因此您可以避免对您的业务模型进行任何更改。然而,因此 dynamic
类型仅在运行时解析,无法确保 属性 Colour
确实存在于该类型上。
添加一个包含颜色的界面(IColorful)。设置您的汽车和自行车以实现该接口。创建并调用函数:
List<IColorful> FindByColor(IEnumerable<IColorful> list, string color)
{
List<IColorful> result = list.Where(item => item.Color == color).ToList();
return result;
}
这样称呼它:
var entities = FindByColor(_Entities.Cars, color);
entities.AddRange(FindByColor(_Entities.Bikes, color))
首先要么定义它们都派生自的基 class,要么定义它们都实现的接口。我将从这里假设他们实现了一个 IColoured
接口和 Colour
属性。 (虽然我会注意到在成员名称中使用 en-US 很常见,因此颜色由 Color
属性 表示)。
所以,假设您的汽车 class 是由 EF 创建的:
namespace SomeNamespace
{
public partial class Cars
{
/*…*/
public string Colour { get; set; }
/*…*/
}
}
然后你可以有一个文件:
namespace SomeNamespace
{
public partial class Cars : IColoured
{
}
}
因为在编译 class 定义时将两个 partial
代码组合在一起,您的代码只需要指示接口已实现,匹配 属性 的事实在另一个文件无关紧要。
然后:
public static IQueryable<T> FilterByColour<T>(this IQueryable<T> source, string colour)
where T : IColoured
{
return source.Where(p => p.Colour == colour);
}
现在您可以使用 _Entities.Cars.FilterByColour("white")
、_Entities.Bikes.FilterByColour("blue")
等。如果按 "white"
过滤是一种特别常见的情况,那么:
重要提示:如果您没有充分的理由(例如使用不是与 EF 兼容),请使用 IQueryable<>
,以便它仍由 EF 处理,并且可以在数据库上进行过滤,而不是从数据库中检索所有内容并在您的应用程序中进行过滤。
public static IQueryable<T> FilterWhite<T>(this IQueryable<T> source)
where T : IColoured
{
return source.FilterByColour("white");
}
或者,如果 FilterByColour 没有其他用途,那么:
public static IQueryable<T> FilterWhite<T>(this IQueryable<T> source)
where T : IColoured
{
return source.Where(p => p.Colour == "white");
}
会起作用。