【问题标题】:dynamic linq to entities to comply with DRY动态链接到实体以遵守 DRY
【发布时间】:2015-06-10 09:16:49
【问题描述】:

有没有办法动态地执行以下操作,所以我不必重复自己?

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;
}

【问题讨论】:

    标签: c# asp.net linq linq-to-entities


    【解决方案1】:

    如果 Cars 和 Bikes 实现了一个通用接口,比如 IVehicle,它具有 Color 属性,您可以定义一个函数:

    public IEnumerable<IVehicle> GetWhiteVehicles(IEnumerable<IVehicle> vehicles) {
      return vehicles.Where(p => p.Colour == "White");
    }
    

    然后

    var result = GetWhiteVehicles(_Entities.Cars);
    var result = GetWhiteVehicles(_Entities.Bikes);
    

    如果 Cars 和 Bikes 是从 Entity Framework 生成的类,您仍然可以通过添加具有同名类的部分定义的新源文件来使它们实现接口:

    public partial class Bikes : IVehicle { }
    public partial class Cars : IVehicle { }
    

    【讨论】:

    • 是的,但我需要 GetWhiteVehicles 的返回类型为 List、Lis 等。
    • 它们属于那种类型,它不仅仅是指定的。只需明确定义变量: List result = GetWhiteVehicles(_Entities.Cars).ToList();或在函数内添加 ToList()
    • 另一件事。我的类确实是从实体框架生成的。添加新的源文件是什么意思?
    • 或者让它更抽象一点: public List GetWhiteVehicles(IEnumerable车辆) where T : class, IVehicle { return vehicle.Where(p => p .Color == "白色").ToList(); }
    • @user441365:实体框架生成了一个文件,比如 Bikes.cs。您不想更改该文件,因为下次生成实体时,您的更改将丢失。因此,您只需创建一个新文件,例如 Bikes.Custom.cs 并将您添加的内容放入其中(公共部分类 Bikes : IVehicle { })。因此,即使 Entity Framework 因重新生成而更改了 Bikes.cs 文件,Bikes 始终会实现您的接口。
    【解决方案2】:

    添加一个包含颜色的界面(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))
    

    【讨论】:

    • 为什么在内存中而不是在数据库中这样做?
    【解决方案3】:

    这应该可行:

    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 确实存在于该类型上。

    【讨论】:

    • @user441365 现在应该
    • 我会避免在不必要的时候使用反射。
    • @JonHanna 不涉及反思。但是它也有同样的缺点,因为它不能保证Colour 确实存在于实例上。
    • 是的,返回值是动态的,而不是实际的 Car 实体
    • @user441365 随意投射。
    【解决方案4】:

    首先要么定义一个它们都派生自的基类,要么定义一个它们都实现的接口。我将从这里假设他们实现了一个带有Colour 属性的IColoured 接口。 (虽然我会注意到在成员名称中使用 en-US 很常见,因此颜色由 Color 属性表示)。

    假设您的 Cars 类是由 EF 创建的:

    namespace SomeNamespace
    {
      public partial class Cars
      {
        /*…*/
        public string Colour { get; set; }
        /*…*/
      }
    }
    

    然后你可以有一个文件:

    namespace SomeNamespace
    {
      public partial class Cars : IColoured
      {
      }
    }
    

    因为在编译类定义时将两个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 不兼容的东西),切勿将这种方法定义为采用 IEnumerable&lt;&gt;,请使用 @ 987654332@ 所以它仍在由 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");
    }
    

    会工作的。

    【讨论】:

      猜你喜欢
      • 2021-09-20
      • 1970-01-01
      • 2017-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-20
      相关资源
      最近更新 更多