代码重用Linq-to-Sql - 创建“通用”查找表

时间:2009-08-24 02:47:08

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

我正在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<Colour>转换为System.Data.Linq.Table<IAttribute>

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

道歉,这是一个大脑倾销。这里确实缺少信息,所以如果您想了解更多细节,请告诉我。干杯!

2 个答案:

答案 0 :(得分:1)

您有2个选项。

  1. 使用Expression Trees动态创建lambda表达式
  2. 使用Scott Gu的博客
  3. 上详述的Dynamic LINQ

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

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

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

答案 1 :(得分:1)

您可以使用查找字典,而不是使用switch语句。这是psuedocode-ish,但这是让你的表有问题的一种方法。你必须手动维护字典,但它应该比交换机容易得多。

看起来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<T>和IRepositoryResolver的实现,以获取通用存储库模式。这对IoC容器非常有效,但如果性能可以接受,您可以使用反射手动创建它们。如果您已经或可以在项目中添加IoC容器,我将使用此路由。如果你走这条路,你需要确保你的IoC容器支持开放式泛型,但我很确定所有主要的玩家都这样做。