ling to sql更新实体非常费劲!
一般网上的例子中都是这样的。
但是,貌似在分层系统中,数据库操作会写到数据访问层,定义实体,抽象出接口。
实体类
数据访问接口
但是我在更新的时候出现了问题。
网上也有解决方案,就是加IsVersion字段,感觉怪怪的。所以我认命了,MS让我怎么办我就怎么办,我让一个Request共用一个DataContext实例。
ASP.NET MVC + EntLib4 + LinQ 整合
第一步,把EntLib的Unity作为ASP.NET MVC Controller管理容器。
创建自定义的Controller工厂,通过Unity实力话Controller。
在Global.asax.cs加上初始化UnityContaner的代码。
web.config配置
以上就是整合Unity的代码,EntLib的详细不配置就不贴了。
下面,扩展Unity,Unity的生命周期管理只有,transient,external,singleton,我要增加一个request的,一个request请求一个实例,然后在request介绍的时候,回收资源。
首先,定义自己的DataContext
第二,增加一个Resquest级别的LifetimeManager,HttpContext.Items中数据是Request期间共享数据用的,所以HttpContext.Items中放一个字典,用类型为key,类型的实例为value。如果当前Context.Items中有类型的实例,就直接返回实例。
写一个HttpMoudle,在Request结束的时候回收资源。
最后,把他们变成Unity的扩展。
在webconfig的配置文件中增加
那么在数据访问对象实现就可以这样写
在Controller中也可以直接注入
DataContext本身是有缓存的,整个Request内都是一个DataContext,DataContext一级缓存能力进一步利用,当然,二级缓存才是王道。
一般网上的例子中都是这样的。
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一级缓存能力进一步利用,当然,二级缓存才是王道。
相关推荐
映射LINQ到数据库 – LINQ to SQL定义新的C# 类、properties、attributes,通过在程序中映射数据库表到实体对象,可以与数据库表交互。 DataContext 类 – 该类支持LINQ的ORM功能。
3. **查询与更新**:LInq To Sql提供了类似LInq To Xml的查询语法,可以方便地对数据库进行查询、插入、更新和删除操作。例如,`var result = from customer in db.Customers where customer.City == "New York" ...
本教程主要涵盖了两个核心部分:LINQ to SQL 和 LINQ to XML,都是针对不同类型数据源进行查询的工具。 ### LINQ to SQL LINQ to SQL 是一种对象关系映射(ORM)框架,允许开发者使用C#或VB.NET语言直接对SQL...
### LINQ to SQL 的增删改查详解 在.NET框架中,LINQ to SQL作为Microsoft提供的对象关系映射(ORM)技术,为开发者提供了一种更简洁、更强大的方式来处理数据库操作。它允许开发人员使用面向对象的方式进行数据...
首先,理解Linq to SQL的基本概念:通过定义数据上下文(DataContext),我们可以将数据库表映射到C#类。这些类成为实体类,它们包含了数据库表中的列属性。一旦定义了这些实体类,我们就可以使用Linq to SQL的查询...
DataContext是LINQ to SQL的核心,它负责将C#代码中的查询转换为SQL语句,与数据库进行交互,同时将数据返回给应用程序。它作为数据访问层的入口点,提供了一种面向对象的方式来处理数据库操作。 2. **功能** - *...
Linq To Sql是.NET Framework中的一个数据访问技术,它是Language Integrated Query(LINQ)的一部分,允许开发人员使用C#或VB.NET等强类型语言进行数据库查询,使得代码更加简洁、易读且类型安全。本文将深入探讨...
1. **数据上下文(DataContext)**:这是Linq to SQL的核心类,它代表了与数据库的会话。通过实例化DataContext,我们可以连接到特定的数据库,并通过其方法和属性访问数据库中的表和存储过程。 2. **实体类映射**...
2. **DataContext对象**:DataContext是LINQ to SQL的核心组件,它是连接应用程序和数据库的桥梁。它管理着所有从数据库中加载的实体对象,并负责将对象的变化同步回数据库。 3. **延迟加载(Lazy Loading)**:...
1. **对象标识属性**:在LINQ to SQL的DataContext类中,每个表映射为一个强类型的数据上下文类,其成员对应于数据库表中的列。当某个成员被标记为标识(Identity)时,意味着它代表了数据库中的主键。在C#中,这...
本文将详细介绍如何在.NET 3.5平台上使用LINQ to SQL来构建一个多层Web应用系统,并重点介绍如何利用LINQ to SQL简化数据访问层的开发工作。 #### 二、LINQ to SQL简介 LINQ to SQL是一种用于.NET Framework的数据...
"Linq to sql"是LINQ的一个重要组成部分,专用于处理关系数据库的数据访问。 在传统的ADO.NET开发中,我们需要手动编写SQL语句来与数据库交互,这不仅增加了代码的复杂性,还容易引入SQL注入等安全问题。而LINQ to ...
为了解决这一问题,开发者可以利用LINQ to SQL的异步查询操作。异步查询在本质上是将查询操作分成了两个部分:请求数据库服务和数据返回。在异步查询中,当主线程将查询任务发送到数据库服务器之后,它会立即释放...
本教程的第37讲和第38讲聚焦于Linq to SQL技术,这是微软提出的一种强大的数据查询语言,它将面向对象编程与SQL数据库查询紧密结合,简化了数据访问和操作。 Linq(Language Integrated Query,语言集成查询)是C# ...
- `DataContext`: 这是LINQ to SQL的主要入口点,它代表与数据库的连接,并提供对象化SQL数据模型的方法。你可以通过它来映射数据库表为.NET类,并执行数据库操作。 - `Table<T>`: 这是一个泛型类,表示数据库表的...
在LINQ-to-SQL数据上下文中,我们通常会先创建一个数据模型,然后通过`SubmitChanges`方法将对象状态的变化同步到数据库。然而,对于批量操作,我们需要在不使用数据上下文的情况下执行`SqlBulkCopy`,因为它的设计...
1. **DataContext**:是LINQ to SQL的主要入口点,它代表与数据库的会话,并管理数据库对象的映射。 2. **实体类**:根据数据库表自动生成的类,这些类可以直接用于表示数据库中的记录。 3. **查询**:使用LINQ...
我们将探讨如何创建LINQ to SQL数据模型,以及如何使用DataContext对象执行查询。 5. LINQ to XML:在XML处理方面,LINQ提供了高效且直观的方式。我们将学习如何使用LINQ to XML创建、修改和查询XML文档,以及如何...