【问题标题】:Linq2SQL+Repository pattern: how to implement type related mappingLinq2SQL+Repository 模式:如何实现类型相关映射
【发布时间】:2011-01-06 21:34:40
【问题描述】:

我已经实现了存储库模式以通过 Linq2Sql ORM 访问数据库数据:

public abstract class RepositoryBase<T, TDb> : IRepository<T>
    where T : IEntity
    where TDb : class, IDbEntity, new()
{
    protected RepositoryBase(IUnityContainer container)
    {
        _container = container;

        _context = _container.Resolve<CMCoreDataClassesDataContext>();
    }

    public IQueryable<T> GetAll()
    {
        return GetTable().Select(GetConverter());
    }

    protected abstract Table<TDb> GetTable();
    protected abstract Expression<Func<TDb, T>> GetConverter();

    protected CMCoreDataClassesDataContext Context { get { return _context; } }

    private readonly IUnityContainer _container;
    private readonly CMCoreDataClassesDataContext _context;
}

以下是特定存储库实现的示例:

public class CustomerProductRepository
    : RepositoryBase<ICommonCustomerProduct, CMCoreDAL.DbData.CustomerProduct>
{
    protected override Table<CMCoreDAL.DbData.CustomerProduct> GetTable()
    {
        return Context.CustomerProducts;
    }

    protected override Expression<Func<CMCoreDAL.DbData.CustomerProduct, ICommonCustomerProduct>> GetConverter()
    {
        return dbEntity => dbEntity.ProdId == (int)ProductType.ProductTypeEnum.CommonProduct
                    ? new CommonCustomerProduct
                    {
                        UnityContainer = UnityContainer,
                        InstanceId = dbEntity.InstanceId,
                        CustomerId = dbEntity.CustomerID,
                        StatusCode = dbEntity.StatusCode,

                        DeviceLicenses = dbEntity.DeviceLicenses,
                        ServerLicenses = dbEntity.ServerLicenses,
                    }
                    : new SpecificCustomerProduct()
                    {
                        UnityContainer = UnityContainer,
                        InstanceId = dbEntity.InstanceId,
                        CustomerId = dbEntity.CustomerID,
                        StatusCode = dbEntity.StatusCode,

                        UserLicenses = dbEntity.DeviceLicenses,
                    }
         ;
    }

这里SpecificCustomerProduct继承自CommonCustomerProduct。

提供的源代码显示了数据库中的记录如何根据实例类型映射到不同的实例。这些类有很多共同的领域,只有少数是不同的。

我对此代码有 2 个顾虑:

  1. 一些重复的赋值操作;
  2. 可读性低:为了添加更多具体的类,我需要制作不可读的链:

    return dbEntity => dbEntity.ProdId == iType1
                    ? new Type1
                    {
                        ... assignments
                    }
                    : 
                    {
                        dbEntity.ProdId == iType2
                        ? new Type2
                        {
                            ... assignments
                        }
                        : new Type3
                        {
                            ... assignments
                        }
                    }
    

有没有更好的方法来实现这种模式的“类型相关”映射?

【问题讨论】:

    标签: c# linq-to-sql orm


    【解决方案1】:

    你看过LINQ to SQL's Inheritance mapping吗?它允许您将不同的类映射到一个公共表,使用数据库列(类型鉴别器)来确定要生成哪种类型的对象。

    【讨论】:

    • 是的,我看过。但我不明白它对我有什么帮助。我仍然可以通过 CustomerProductRepository 类访问表,在这种情况下接收我需要重新映射的数据库实体。而且我看不到将数据库实体重新映射到业务实体的简单方法。我看不出“特定于数据”的实体将如何提供帮助。
    • 您需要做的是在您的 dbml 中定义 SpecificCustomerProduct 和 CommonCustomerProduct 实体,并在它们和 CustomerProduct 之间建立继承关联,我假设这是您当前在 dbml 中定义的实体.在继承关联中,将 CustomerProduct.ProdID 设置为鉴别器列。然后,当您对 CustomerProduct 表进行任何查询时,返回的实体将自动为继承类型 - 不需要映射。要自定义继承的类,请为每个类创建一个单独的部分类文件并编辑掉。
    • 猜猜,为每个继承的类拥有一个单独的存储库类(可能具有共享功能的基本存储库类)会很好。我说的对吗?
    • 你知道,我不确定。我想您可以先尝试仅使用基类 - 即使您通过基类表查询,LINQ to SQL 也会自动生成继承的类型。因此,如果您的 CustomerProduct 数据库表包含继承类型的鉴别器值,那么像 context.CustomerProduct.ToList() 这样的查询将包含基本类型和继承类型的混合。但至于如何处理您的存储库代码,我不确定。这可能是一个很好的问题......
    猜你喜欢
    • 1970-01-01
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-04
    • 2021-11-10
    • 2013-05-11
    相关资源
    最近更新 更多