`
周富贵
  • 浏览: 15481 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

同步DataContext,解决linq to sql更新数据的问题!!!

    博客分类:
  • .NET
阅读更多
ling to sql更新实体非常费劲!
一般网上的例子中都是这样的。
Customer cust = db.Customers.First(c => c.CustomerID == "ALFKI");
cust.ContactTitle = "Vice President";
db.SubmitChanges();

但是,貌似在分层系统中,数据库操作会写到数据访问层,定义实体,抽象出接口。

实体类
    /// <summary>
    /// 计划任务
    /// </summary>
    [Table(Name = "EDM_TaskPlan")]
    public class TaskPlan
    {
        /// <summary>
        /// 计划编码
        /// </summary>
        [Column(IsDbGenerated=true,IsPrimaryKey=true,Name="PlanID")]
        public int PlanID { get; set; }

        /// <summary>
        /// 任务名称
        /// </summary>
        [Column(Name="PlanName")]
        public string Name { get; set; }

        /// <summary>
        /// 任务描述
        /// </summary>
        [Column]
        public string Description { get; set; }

        /// <summary>
        /// 星期一定义
        /// </summary>
        [Column]
        public string MondayDef { get; set; }

        /// <summary>
        /// 星期二定义
        /// </summary>
        [Column]
        public string TuesdayDef { get; set; }

        /// <summary>
        /// 星期三定义
        /// </summary>
        [Column]
        public string WednesdayDef { get; set; }

        /// <summary>
        /// 星期四定义
        /// </summary>
        [Column]
        public string ThursdayDef { get; set; }

        /// <summary>
        /// 星期五定义
        /// </summary>
        [Column]
        public string FridayDef { get; set; }

        /// <summary>
        /// 星期六定义
        /// </summary>
        [Column]
        public string SaturdayDef { get; set; }

        /// <summary>
        /// 星期日定义
        /// </summary>
        [Column]
        public string SundayDef { get; set; }
    }


数据访问接口
    /// <summary>
    /// 任务计划数据访问接口
    /// </summary>
    public interface ITaskPlanDao
    {
        /// <summary>
        /// 查找全部
        /// </summary>
        /// <returns></returns>
        TaskPlan[] FindAll();

        /// <summary>
        /// 根据编码查找
        /// </summary>
        /// <param name="id">计划任务编码</param>
        /// <returns></returns>
        TaskPlan FindByID(int id);

        /// <summary>
        /// 保存或更新
        /// </summary>
        /// <param name="taskPlan">任务计划对象</param>
        /// <returns></returns>
        int SaveOrUpdate(TaskPlan taskPlan);

        /// <summary>
        /// 根据编码删除
        /// </summary>
        /// <param name="id">任务计划编码</param>
        /// <returns></returns>
        void DeleteByID(int id);
    }


但是我在更新的时候出现了问题。
dbContext.Attach(taskPlan);
//根本不会更新
dbContext.Attach(taskPlan,true);
//An entity can only be attached as modified without original state if it //declares a version member or does not have an update check policy
dbContext.Attach(taskPlan,this.FindByID(taskPlan.PlanID));
//Cannot add an entity with a key that is already in use.


网上也有解决方案,就是加IsVersion字段,感觉怪怪的。所以我认命了,MS让我怎么办我就怎么办,我让一个Request共用一个DataContext实例

ASP.NET MVC + EntLib4 + LinQ 整合
第一步,把EntLib的Unity作为ASP.NET MVC Controller管理容器。

创建自定义的Controller工厂,通过Unity实力话Controller。
    /// <summary>
    /// EntLib IoC容器和ASP.NET MVC Controller集成工厂。
    /// </summary>
    public class UnityControllerFactory : DefaultControllerFactory
    {
        private IUnityContainer unityContaier;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="unityContaier">EntLib IOC容器</param>
        public UnityControllerFactory(IUnityContainer unityContaier)
        {
            this.unityContaier = unityContaier;
        }


        #region IControllerFactory Members

        protected override IController CreateController(RequestContext context, string controllerName)
        {
            Type type = base.GetControllerType(controllerName);
            return unityContaier.Resolve(type) as IController;
        }

        #endregion
    }


在Global.asax.cs加上初始化UnityContaner的代码。
        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);

            this.InitializeContainer();
        }

        protected virtual void InitializeContainer()
        {
            IUnityContainer container = new UnityContainer();

            UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
            section.Containers["dataContainer"].Configure(container);

            Type controllerType = typeof(IController);
            foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
            {
                if (controllerType.IsAssignableFrom(type))
                {
                    container.RegisterType(type, type);
                }
            }

            UnityControllerFactory factory = new UnityControllerFactory(container);
            ControllerBuilder.Current.SetControllerFactory(factory);
        }


web.config配置
  <unity>
    <typeAliases>
      <typeAlias alias="transient"
           type="Microsoft.Practices.Unity.TransientLifetimeManager,
             Microsoft.Practices.Unity" />
    </typeAliases>
    <containers>
      <container name="dataContainer">
        <types>
          <type type="Shengjing360.EDM.Task.Daos.ITaskPlanDao,Shengjing360.EDM.Task" mapTo="Shengjing360.EDM.Task.DaoImpl.TaskPlanDaoImpl,Shengjing360.EDM.Task.DaoImpl">
            <lifetime type="transient" />
          </type>
        </types>
        <extensions>
          <add type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity.EnterpriseLibraryCoreExtension, Microsoft.Practices.EnterpriseLibrary.Common" />
          <add type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.Unity.DataAccessBlockExtension, Microsoft.Practices.EnterpriseLibrary.Data" />
        </extensions>
      </container>
    </containers>
  </unity>


以上就是整合Unity的代码,EntLib的详细不配置就不贴了。

下面,扩展Unity,Unity的生命周期管理只有,transient,external,singleton,我要增加一个request的,一个request请求一个实例,然后在request介绍的时候,回收资源。

首先,定义自己的DataContext
    public class ShengjingDataContext : DataContext
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="db"></param>
        [InjectionConstructor]
        public ShengjingDataContext([Dependency]Database db ) : base(db.CreateConnection())
        {
            this.Database = db;

            this.Log = Console.Out;
        }

        /// <summary>
        /// 数据库
        /// </summary>
        public Database Database { get; private set; }
    }

第二,增加一个Resquest级别的LifetimeManager,HttpContext.Items中数据是Request期间共享数据用的,所以HttpContext.Items中放一个字典,用类型为key,类型的实例为value。如果当前Context.Items中有类型的实例,就直接返回实例。
    public class RequestScopeLifetimeManager : LifetimeManager
    {
        private Type objectType;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="t"></param>
        public RequestScopeLifetimeManager(Type t) 
        {
            this.objectType = t;
        }

        private IDictionary<Type,object> GetObjectTable()
        {
            IDictionary<Type, object> objects = HttpContext.Current.Items[UnityHttpMoudle.UNITY_OBJECTS] 
                as IDictionary<Type, object>;
            if (objects == null)
            {
                lock (this)
                {
                    if (HttpContext.Current.Items[UnityHttpMoudle.UNITY_OBJECTS] == null)
                    {
                        objects = new Dictionary<Type, object>();
                        HttpContext.Current.Items[UnityHttpMoudle.UNITY_OBJECTS] = objects;
                    }
                    else
                    {
                        return HttpContext.Current.Items[UnityHttpMoudle.UNITY_OBJECTS]
                            as IDictionary<Type, object>;
                    }
                }
            }
            return objects;
        }

        public override object GetValue()
        {
            IDictionary<Type, object> objects = this.GetObjectTable();
            object obj = null;
            if (objects.TryGetValue(this.objectType,out obj))
            {
                return obj;
            }
            return null;
        }

        public override void RemoveValue()
        {
            IDictionary<Type, object> objects = this.GetObjectTable();
            object obj = null;
            if (objects.TryGetValue(this.objectType, out obj))
            {
                ((IDisposable)obj).Dispose();
                objects.Remove(this.objectType);
            }
        }

        public override void SetValue(object newValue)
        {
            IDictionary<Type, object> objects = this.GetObjectTable();
            objects.Add(this.objectType, newValue);
        }
    }

写一个HttpMoudle,在Request结束的时候回收资源。
    public class UnityHttpMoudle : IHttpModule
    {
        internal const string UNITY_OBJECTS = "UNITY_OBJECTS";

        #region IHttpModule Members

        public void Dispose()
        {
            
        }

        public void Init(HttpApplication context)
        {
            context.EndRequest += new EventHandler(context_EndRequest);
        }

        private void context_EndRequest(object sender, EventArgs e)
        {
            IDictionary<Type, object> objects = HttpContext.Current.Items[UNITY_OBJECTS] 
                as IDictionary<Type, object>;
            if (objects != null)
            {
                foreach (Type key in objects.Keys)
                {
                    if (objects[key] is IDisposable)
                    {
                        ((IDisposable)objects[key]).Dispose();
                    }
                }
                HttpContext.Current.Items.Remove(UNITY_OBJECTS);
            }
        }

        #endregion
    }

最后,把他们变成Unity的扩展。
    public class ShengjingExtension : UnityContainerExtension
    {
        protected override void Initialize()
        {
            this.Container.RegisterType<RequestScopeLifetimeManager, RequestScopeLifetimeManager>();

            this.Container.RegisterType<ShengjingDataContext, ShengjingDataContext>(new RequestScopeLifetimeManager(typeof(ShengjingDataContext)));
        }
    }

在webconfig的配置文件中增加
<unity>
……
<extensions>
……
<add type="Shengjing360.Utility.ShengjingExtension,Shengjing360.Utility" />
</extensions>
<unity>
……
<httpModules>
……
      <add name="UnityModule" type="Shengjing360.Utility.UnityHttpMoudle,Shengjing360.Utility"/>
    </httpModules>


那么在数据访问对象实现就可以这样写
    public class TaskPlanDaoImpl : ITaskPlanDao
    {
        private ShengjingDataContext dbContext;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbContext"></param>
        [InjectionConstructor]
        public TaskPlanDaoImpl([Dependency]ShengjingDataContext dbContext)
        {
            this.dbContext = dbContext;
        }

        #region ITaskPlanDao Members

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public TaskPlan[] FindAll()
        {
            var taskPlans = from taskPlan in dbContext.GetTable<TaskPlan>()
                            orderby taskPlan.PlanID descending
                            select taskPlan;

            return taskPlans.ToArray<TaskPlan>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public TaskPlan FindByID(int id)
        {
            var taskPlans = from taskPlan in dbContext.GetTable<TaskPlan>()
                            where taskPlan.PlanID == id
                            select taskPlan;

            if (taskPlans.Count() > 0)
            {
                return taskPlans.First<TaskPlan>();
            }
            return null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="taskPlan"></param>
        /// <returns></returns>
        public int SaveOrUpdate(TaskPlan taskPlan)
        {
            Table<TaskPlan> table = this.dbContext.GetTable<TaskPlan>();
            if (taskPlan.PlanID == 0)
            {
                table.InsertOnSubmit(taskPlan);
            }

            this.dbContext.SubmitChanges();
            return taskPlan.PlanID;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        public void DeleteByID(int id)
        {
            Table<TaskPlan> table = this.dbContext.GetTable<TaskPlan>();
            table.DeleteOnSubmit(table.First<TaskPlan>(p => p.PlanID == id));
            this.dbContext.SubmitChanges();
        }

        #endregion
    }


在Controller中也可以直接注入
        [Dependency]
        public ITaskPlanDao taskPlanDao { get; set; }

……

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public ActionResult SaveOrUpdate()
        {
            int planID = String.IsNullOrEmpty(this.Request.Form["PlanID"]) ?
                0 :
                Int32.Parse(this.Request.Form["PlanID"]);

            TaskPlan taskPlan = planID == 0 ?
                new TaskPlan() { PlanID = planID } :
                this.taskPlanDao.FindByID(planID);

            taskPlan.Name = this.Request.Form["Name"].Trim();
            taskPlan.Description = this.Request.Form["Description"].Trim();
            taskPlan.MondayDef = this.Request.Form["MondayDef"].Trim();
            taskPlan.SaturdayDef = this.Request.Form["SaturdayDef"].Trim();
            taskPlan.SundayDef = this.Request.Form["SundayDef"].Trim();
            taskPlan.ThursdayDef = this.Request.Form["ThursdayDef"].Trim();
            taskPlan.TuesdayDef = this.Request.Form["TuesdayDef"].Trim();
            taskPlan.WednesdayDef = this.Request.Form["WednesdayDef"].Trim();
            taskPlan.FridayDef = this.Request.Form["FridayDef"].Trim();

            this.taskPlanDao.SaveOrUpdate(taskPlan);
            return this.RedirectToAction("Browse");
        }

DataContext本身是有缓存的,整个Request内都是一个DataContext,DataContext一级缓存能力进一步利用,当然,二级缓存才是王道。
2
1
分享到:
评论

相关推荐

    用LINQ to SQL 进行数据访问、更新和删除(附Demo示例程序下载)

    映射LINQ到数据库 – LINQ to SQL定义新的C# 类、properties、attributes,通过在程序中映射数据库表到实体对象,可以与数据库表交互。 DataContext 类 – 该类支持LINQ的ORM功能。

    LInq入门宝典 Linq To Xml linq to sql

    3. **查询与更新**:LInq To Sql提供了类似LInq To Xml的查询语法,可以方便地对数据库进行查询、插入、更新和删除操作。例如,`var result = from customer in db.Customers where customer.City == "New York" ...

    LINQ教程中文版(LINQ TO SQL ,LINQ TO XML)

    本教程主要涵盖了两个核心部分:LINQ to SQL 和 LINQ to XML,都是针对不同类型数据源进行查询的工具。 ### LINQ to SQL LINQ to SQL 是一种对象关系映射(ORM)框架,允许开发者使用C#或VB.NET语言直接对SQL...

    linq to sql 增删改查

    ### LINQ to SQL 的增删改查详解 在.NET框架中,LINQ to SQL作为Microsoft提供的对象关系映射(ORM)技术,为开发者提供了一种更简洁、更强大的方式来处理数据库操作。它允许开发人员使用面向对象的方式进行数据...

    C#实现Siliverlight的LInq to sql的数据绑定

    首先,理解Linq to SQL的基本概念:通过定义数据上下文(DataContext),我们可以将数据库表映射到C#类。这些类成为实体类,它们包含了数据库表中的列属性。一旦定义了这些实体类,我们就可以使用Linq to SQL的查询...

    C# .net LINQ TO SQL 进阶入门经典

    DataContext是LINQ to SQL的核心,它负责将C#代码中的查询转换为SQL语句,与数据库进行交互,同时将数据返回给应用程序。它作为数据访问层的入口点,提供了一种面向对象的方式来处理数据库操作。 2. **功能** - *...

    Linq To Sql进阶

    Linq To Sql是.NET Framework中的一个数据访问技术,它是Language Integrated Query(LINQ)的一部分,允许开发人员使用C#或VB.NET等强类型语言进行数据库查询,使得代码更加简洁、易读且类型安全。本文将深入探讨...

    Linq to SQL入门代码

    1. **数据上下文(DataContext)**:这是Linq to SQL的核心类,它代表了与数据库的会话。通过实例化DataContext,我们可以连接到特定的数据库,并通过其方法和属性访问数据库中的表和存储过程。 2. **实体类映射**...

    LINQ to SQL语句(17)之对象加载

    2. **DataContext对象**:DataContext是LINQ to SQL的核心组件,它是连接应用程序和数据库的桥梁。它管理着所有从数据库中加载的实体对象,并负责将对象的变化同步回数据库。 3. **延迟加载(Lazy Loading)**:...

    LINQ to SQL语句(16)之对象标识

    1. **对象标识属性**:在LINQ to SQL的DataContext类中,每个表映射为一个强类型的数据上下文类,其成员对应于数据库表中的列。当某个成员被标记为标识(Identity)时,意味着它代表了数据库中的主键。在C#中,这...

    PDF_在.NET 3.5 平台上使用LINQ to SQL创建三层多层Web应用系统

    本文将详细介绍如何在.NET 3.5平台上使用LINQ to SQL来构建一个多层Web应用系统,并重点介绍如何利用LINQ to SQL简化数据访问层的开发工作。 #### 二、LINQ to SQL简介 LINQ to SQL是一种用于.NET Framework的数据...

    Linq to sql

    "Linq to sql"是LINQ的一个重要组成部分,专用于处理关系数据库的数据访问。 在传统的ADO.NET开发中,我们需要手动编写SQL语句来与数据库交互,这不仅增加了代码的复杂性,还容易引入SQL注入等安全问题。而LINQ to ...

    LINQ to SQL异步查询技术在Web开发中的应用.pdf

    为了解决这一问题,开发者可以利用LINQ to SQL的异步查询操作。异步查询在本质上是将查询操作分成了两个部分:请求数据库服务和数据返回。在异步查询中,当主线程将查询任务发送到数据库服务器之后,它会立即释放...

    VS2010轻松学习C#-从零到深入-天轰穿.NET4趣味编程视频教程_第37讲&第38讲:Linq to SQL

    本教程的第37讲和第38讲聚焦于Linq to SQL技术,这是微软提出的一种强大的数据查询语言,它将面向对象编程与SQL数据库查询紧密结合,简化了数据访问和操作。 Linq(Language Integrated Query,语言集成查询)是C# ...

    SystemDataLinq命名空间问题解决

    - `DataContext`: 这是LINQ to SQL的主要入口点,它代表与数据库的连接,并提供对象化SQL数据模型的方法。你可以通过它来映射数据库表为.NET类,并执行数据库操作。 - `Table&lt;T&gt;`: 这是一个泛型类,表示数据库表的...

    将SQL批量复制与LINQ-to-SQL数据上下文一起使用

    在LINQ-to-SQL数据上下文中,我们通常会先创建一个数据模型,然后通过`SubmitChanges`方法将对象状态的变化同步到数据库。然而,对于批量操作,我们需要在不使用数据上下文的情况下执行`SqlBulkCopy`,因为它的设计...

    Linq增删改查源文件带数据库

    1. **DataContext**:是LINQ to SQL的主要入口点,它代表与数据库的会话,并管理数据库对象的映射。 2. **实体类**:根据数据库表自动生成的类,这些类可以直接用于表示数据库中的记录。 3. **查询**:使用LINQ...

    精通LINQ数据访问技术第10章

    我们将探讨如何创建LINQ to SQL数据模型,以及如何使用DataContext对象执行查询。 5. LINQ to XML:在XML处理方面,LINQ提供了高效且直观的方式。我们将学习如何使用LINQ to XML创建、修改和查询XML文档,以及如何...

Global site tag (gtag.js) - Google Analytics