【问题标题】:Code re-use with Linq-to-Sql - Creating 'generic' look-up tables使用 Linq-to-Sql 重用代码 - 创建“通用”查找表
【发布时间】:2010-11-22 03:50:31
【问题描述】:

我目前正在 ASP.NET MVC 中开发一个应用程序,该应用程序有许多查找表,所有表单

LookUp {
  Id
  Text
}

如您所见,这只是将 Id 映射到文本值。这些用于诸如颜色之类的东西。我现在有很多,目前有 6 个,而且可能很快会更多。

我正在尝试组合一个可通过 AJAX 使用的 API,以允许用户从这些查找表中添加/列出/删除值,因此例如我可以有类似的东西:

http://example.com/Attributes/Colours/[List/Add/Delete]

我目前的问题是,很明显,无论我使用哪个查找表,一切都完全一样。所以真的不应该有任何重复的代码。

我目前有一个指向“AttributeController”的自定义路由,它根据 URL 计算出有问题的属性/查找表(即http://example.com/Attributes/Colours/List 需要“颜色”表)。我将属性(颜色 - 一个字符串)和操作(列表/添加/删除)以及所需的任何其他参数(如果我想将红色添加到列表中,说“红色”)传回我的存储库,其中实际工作已完成。

这里的事情开始变得混乱,因为目前我已经对属性字符串进行了 switch/case,然后可以获取与特定查找表相对应的 Linq-to-Sql 实体。我发现这很脏,因为我发现自己必须在每个查找实体上编写相同的操作,呃!

我真正想做的是进行某种映射,我可以简单地传入属性名称并获取某种形式的通用查找对象,我可以对其执行所需的操作而无需关心输入。

有什么方法可以对我的 Linq-To-Sql 实体执行此操作吗?我试过让它们实现一个基本接口 (IAttribute),它只是指定 Id/Text 属性,但是这样做会失败:

System.Data.Linq.Table<IAttribute> table = GetAttribute("Colours");

因为我无法将System.Data.Linq.Table&lt;Colour&gt; 转换为System.Data.Linq.Table&lt;IAttribute&gt;

有没有办法让这些查找表“通用”?

抱歉,这有点脑残。这里肯定缺少信息,所以如果您想了解更多详细信息,请告诉我。干杯!

【问题讨论】:

    标签: asp.net-mvc linq-to-sql generics


    【解决方案1】:

    你有两个选择。

    1. 使用Expression Trees 动态创建您的 lambda 表达式
    2. 使用 Dynamic LINQ,具体请参见 Scott Gu 的博客

    我已经查看了这两个选项,并成功地将表达式树实现为我的首选方法。

    这是我创建的示例函数:(未测试)

    private static bool ValueExists<T>(String Value) where T : class
        {
            ParameterExpression pe = Expression.Parameter(typeof(T), "p");
            Expression value = Expression.Equal(Expression.Property(pe, "ColumnName"), Expression.Constant(Value));
            Expression<Func<T, bool>> predicate = Expression.Lambda<Func<T, bool>>(value, pe);
            return MyDataContext.GetTable<T>().Where(predicate).Count() > 0;
        }
    

    【讨论】:

    • 太好了,正是我需要的。表达式树看起来非常适合这项工作:)
    【解决方案2】:

    您可以使用查找字典,而不是使用 switch 语句。这是伪代码,但这是让您的表有问题的一种方法。您必须手动维护字典,但它应该比切换更容易。

    看起来DataContext.GetTable() 方法可以解决您的问题。如果您知道要操作的 linq 实体的类型,则可以获取一个表。

    Dictionary<string, Type> lookupDict = new Dictionary<string, Type>
    {
      "Colour", typeof(MatchingLinqEntity)
      ...
    }
    
    Type entityType = lookupDict[AttributeFromRouteValue];
    YourDataContext db = new YourDataContext();
    var entityTable = db.GetTable(entityType);
    var entity = entityTable.Single(x => x.Id == IdFromRouteValue);
    // or whatever operations you need
    db.SubmitChanges()
    

    Suteki Shop project 有一些 非常 巧妙的工作。您可以查看他们对 IRepository&lt;T&gt; 和 IRepositoryResolver 的实现,以了解通用存储库模式。这确实适用于 IoC 容器,但如果性能可以接受,您可以使用反射手动创建它们。如果您拥有或可以将 IoC 容器添加到项目中,我会使用此路线。如果你走这条路,你需要确保你的 IoC 容器支持开放泛型,但我很确定所有主要参与者都这样做。

    【讨论】:

      猜你喜欢
      • 2019-05-06
      • 2010-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多