龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > asp.net编程 >

续ASP.NET中LINQ to SQL 实现数据访问通用基类(2)

时间:2009-12-21 11:47来源:未知 作者:admin 点击:
分享到:
在我们基于Domain驱动模式开发面向对象的多层架构的时候,层和层之间数据的传输对象(DTO)往往简化为领域对象模型,在上文中就是我们利用LINQ TO SQL对象设计器生成的Bill,Customer等

在我们基于Domain驱动模式开发面向对象的多层架构的时候,层和层之间数据的传输对象(DTO)往往简化为领域对象模型,在上文中就是我们利用LINQ TO SQL对象设计器生成的Bill,Customer等实体类。

存在的问题

通常的做法,我们把这些实体类单独分成一层,这样程序分层划分成如下:

数据访问层(Data Access Layer)
业务层 (Business Layer)
用户界面层(UI Layer)
实体层(Entity Layer)
注意,多层应用程序,一般遵守这样的规则:UI调用BL,BL调用DL,不能跨级调用,也不能底层调用上层,但是实体层是我们的DTO,各个层都可以调用它。

  如果这样划分,我们系统就出现问题:

  我们把RepositoryBase划到数据层,LINQ TO SQL对象设计器生成的类分到实体层,数据层引用实体层,没有问题,但是我们看到,在我们实体层,存在一个方法(以Bill为例):

 

public static RepositoryBase<Bill, LINQtoSQLHelper.DataContextSetUp> CreateRepository() { return new BillRepository(); }
 

数据层也必须引用数据访问层,循环引用。另外,对于如何体现loadoption那?

解决循环引用

 以Bill实体为例,循环引用的病因在于Bill实体中添加这样一个方法:

 

public static RepositoryBase<Bill, LINQtoSQLHelper.DataContextSetUp> CreateRepository() { return new BillRepository(); }
 

为什么要添加这个方法那?这样做就是充血模式的实体了。注意到RepositoryBase.cs有一段代码:

 

Code
try
{
    object Repository = association.OtherType.Type.GetMethod("CreateRepository").Invoke(null, null);
    Repository.GetType().GetMethod("IterateEntitySet",
                                 BindingFlags.NonPublic | BindingFlags.Instance).Invoke(
        Repository,
        new object[4]
        {
            AssociationProperty.GetValue(theEntity, null),
            context,
            OperationMode,
            Recursively
        }
        );
}
catch (System.Reflection.TargetInvocationException e)
{
    throw (e.InnerException);
}

 

作者添加这段代码,主要是利用反射获取当前实体的CreateRepository方法,实现对象的CRUD操作。如果实体中去掉这个CreateRepository方法,那这段代码如何变通,请看:

dd

try

                            {

                                object Repository = association.OtherType.Type.GetMethod("CreateRepository").Invoke(null, null);

                                Repository.GetType().GetMethod("IterateEntitySet",

                                                             BindingFlags.NonPublic | BindingFlags.Instance).Invoke(

                                    Repository,

                                    new object[4]

                                    {

                                        AssociationProperty.GetValue(theEntity, null),

                                        context,

                                        OperationMode,

                                        Recursively

                                    }

                                    );

                            }

                            catch (System.Reflection.TargetInvocationException e)

                            {

                                throw (e.InnerException);

                            }


 

 主要利用反射,从当前数据访问层Assembly中获得对应实体类的的Repository类。

好,解决循环引用问题。

体现loadoption

这个问题比较棘手,确实在底层无法感知业务需求的东西,而其DataContext是共用的。

能不能另辟捷径那?注意我们用泛型构造RepositoryBase类,那能不能从中得到什么那?

我们对类RepositoryBase添加入如下方法:

 

Code


        public IList<TEntityType> Where(string predicate, params object[] values)

        {

            InitDataContext();

            return m_context.GetTable<TEntityType>().Where(predicate, values).ToList<TEntityType>();

        }

 

        public IList<TEntityType> OrderBy(string ordering, params object[] values)

        {

            InitDataContext();

            return m_context.GetTable<TEntityType>().OrderBy(ordering, values).ToList<TEntityType>();

        }

 

        public IList<TEntityType> Take(int count)

        {

            InitDataContext();

            return m_context.GetTable<TEntityType>().Take<TEntityType>(count).ToList<TEntityType>();

        }

 

        public IQueryable Select(string selector, params object[] values)

        {

            InitDataContext();

            return m_context.GetTable<TEntityType>().Select(selector, values);

        }

 

        #endregion

 

        #region Query Methods (Lambda Expression)

 

        public IList<TEntityType> Where(Func<TEntityType, bool> predicate)

        {

            InitDataContext();

            return m_context.GetTable<TEntityType>().Where(predicate).ToList<TEntityType>();

        }

 

,好,这个基本上体现loadoption。

源代码

 更新的源代码,本文可以找到这里

反馈!

本文是对我翻译上一篇文章的一个补从,代码你可以自由使用,但是必须声明出处。

精彩图集

赞助商链接