EF4.1(数据库优先)通用存储库:数据类型不一致的问题

时间:2011-05-16 16:09:32

标签: generics repository-pattern entity-framework-4.1

我正在开发一个使用旧系统数据库的新应用程序。数据库中的每个表(大约有600个)都有一个“已删除”列,用于标记是否应向用户显示该项目。在我的通用存储库中,我需要添加LINQ表达式来过滤掉Deleted == 1 / True的所有项目。

我遇到的问题是“已删除”列在表中具有不同的数据类型。

在任何给定的表格中都是tinyint,smallint或bit。从理论上讲,这不应该是一个大问题,因为数据总是存储为1或0(好吧,应该是,我想,但不管是哪种方式)可以转换为任何特定的上面提到的类型。我只是不确定如何和/或在哪里投下这个。

我创建了一个强制所有实体公开此属性的接口,但由于类型不同,每个具有不同数据类型的实体都会引发问题。我希望(尽管已经知道它不起作用)我可以将接口更改为“对象”或“动态”,这仍然会导致编译时错误,因为EDMX模型正在创建数据模型类。我不想花太多时间在T4模板中编写代码,如果这不能解决问题。

当我更改EDMX模型的实体属性以遵守特定数据类型时,我收到映射错误(“特定于成员映射无效。类型'类型'Edm.Byte []'成员'已删除'类型'MyEntity'与'SqlServer.bit []'....)

不兼容

我怀疑我是否能够更改表中的数据类型,因为有许多不同的应用程序使用此数据库,我确信它会在某处导致问题。

还有其他人遇到类似的情况并想出一个可行的解决方案吗?

[编辑] 我将使用Baldy推荐的解决方案,并创建一个视图来包装表并创建一个额外的列,用于将列转换为一些。

3 个答案:

答案 0 :(得分:1)

您是否可以使用读取已删除位并返回统一且一致的值的分部类在每个模型类中创建自定义只读属性?

答案 1 :(得分:1)

您可能需要考虑使用T-SQL脚本转换表上实际字段的临时任务。

你有没有想过这个?你有什么理由不去做吗?

这可能是一个很好的举措......

答案 2 :(得分:1)

通用方法基于您的实体共享相同行为的事实。在您的情况下,它表示具有相同类型的相同属性。您的实体不符合此要求,因此您无法使用通用方法。

你必须以某种方式注入通用行为。那怎么样:

public interface IDeletable<TVal> where TVal : struct
{
    TVal Deleted { get; set; }
}

public class Entity : IDeletable<bool>
{
    public bool Deleted { get; set; }
    ...
}

public interface IDeletingStrategy<TEntity, TVal> 
    where TEntity : class, IDeletable<TVal>
    where TVal : struct
{
    void Delete(TEntity entity);
    IQueryable<TEntity> GetActive(IQueryable<TEntity> query);
}

public class Repository<TEntity, TVal> 
    where TEntity : class, IDeletable<TVal>
    where TVal : struct
{
   private IDeletingStrategy<TEntity,TVal> _deletingStrategy;

   public Repository(IDeletingStrategy<TEntity, TVal> deletingStrategy)
   {
       _deletingStrategy = deletingStrategy;
   }

   public void Delete(TEntity entity)
   {
       _deletingStrategy.Delete(entity);
       ...
   }

   public IQueryable<TEntity> GetActive()
   {
       return _deletingStrategy.GetActive(context.Set<TEntity>());
   }

}

public class BoolDeletingStrategy<TEntity> : IDeletingStrategy<TEntity, bool>
    where TEntity : class, IDeletable<bool>
{
    public void Delete(TEntity entity)
    {
        entity.Deleted = true;
    }

    public IQueryable<TEntity> GetActive(IQueryable<TEntity> query)
    {
        return query.Where(e => !e.Deleted);
    }
}

您将实例化您的存储库,如:

var repo = new Repository<Entity, bool>(new BoolDeletingStrategy<Entity>());

我没有测试它,但我想它可以工作。