使用LINQ to SQL建模Northwind数据库

在这之前一起学过LINQ to SQL设计器的使用,下面就使用如下的数据模型:

当使用LINQ to SQL设计器设计以上定义的五个类(Product,Category,Customer,Order和OrderDetail)的时候,每个类中的属性 都映射了相应数据库中表的列,每个类的实例则代表了数据库表中的一条记录。另外,当定义数据模型时,LINQ to SQL设计器同样会创建一个自定义DataContext类,来作为数据库查询和应用更新/变化的主要渠道。以上数据模型中定义的DataContext 类命名为“NorthwindDataContext”。该类中包含了代表每个建模数据库表的属性。

使用LINQ语法表达式可以十分简单的使用NorthwindDataContext类来查询和检索数据库中的数据。LINQ to SQL会在运行时自动的转换LINQ表达式到适当的SQL代码来执行。例如,编写以下LINQ表达式来根据Product Name检索单个Product对象:

还可以使用LINQ表达式来检索所有不存在于Order Details中的,并且UnitPrice大于100的所以Product:

变化跟踪和DataContext.SubmitChanges()

当执行查询和检索像Product实例这样的对象时,LINQ to SQL会自动保持对这些对象任何变化或更新的跟踪。我们可以进行任意次数的查询,以及使用LINQ to SQL的DataContext类作出更新,而这些变化都会被全部跟踪。

注意:LINQ to SQL的变化跟踪发生于调用者端——而不是在数据库中。这就意味着使用跟踪不会销耗任何数据库资源,也不需要在数据库中改变/安装任何组件模块。

当对从LINQ to SQL中检索的对象作出更改之后,我们可以选择调用DataContext上的SubmitChange()方法来应用变化返回到数据库。这将会导致 LINQ to SQL动态计算并执行适当的SQL代码来更新数据库。例如,编写以下代码更新数据库中Product Name为“Chai”的Product上的UnitPrice和UnitsInStock:

当在以上代码中调用northwind.SubmitChanges()方法时,LINQ to SQL会动态构建并执行一个更新这两个Product属性值的SQL“UPDATE”代码模块。

在下面代码中我们来遍历不流行的,昂贵的Product,并把它们的ReorderLevel属性设为0:

当在以上代码中调用northwind.SubmitChanges()方法时,LINQ to SQL会计算并执行一组适当的UPDATE代码模块来修改RecorderLevel属性已变化的Product。

注意,如果一个Product的属性没有通过属性指定而发生变化,则该对象不会被认为是发生变化的,并且LINQ to SQL也不会对于该对象执行更新回数据库的操作。例如,如果“Chai”对象的UnitPrice仍旧是$2,UnitsInStock仍旧是4,当调用 SubmitChange()时不会导致任何数据库UPDATE代码模块的执行。相似的,在第二个例子中的那些符合条件的Product中只有 RecorderLevel原来不是0的才会在SubmitChange()被调用时更新。

插入和删除示例

除了更新数据库中已存在的行之外,LINQ to SQL同样支持插入和删除数据。可以通过从DataContext的表集合中添加/移除数据对象,并调用SubmitChange()方法来实现数据库中 的插入和删除操作。LINQ to SQL也会对添加/移除操作保持跟踪,并当SubmitChange()被调用时自动执行适当的SQL中的INSERT或DELETE代码模块。

插入Product

可以通过创建一个新Product实例添加一个新的Product到数据库,设置它的属性,并添加它到DataContext类中的Product集合中:

当在以上代码中调用northwind.SubmitChanges()方法时,在数据库的Product表中会有一条新的记录被创建。

删除Product

与添加相似,可以通过从DataContext类中的Product集合中移除某一产品来表达想要从数据库中删除相应的记录:

在以上代码中先使用LINQ查询检索一系列不会被订购的Product,然后将其传入DataContext类中Product集合上的 RemoveAll()方法。当在以上代码中调用northwind.SubmitChanges()方法时,这些Product记录就会从数据库中的 Product表中删除。

通过关系关联更新

像LINQ to SQL这样十分灵活的O/R映射工具,可以让我们很简单的通过表之间的关系关联来对数据模型建模。例如,可以把每个Product建模到一个 Category中,每个Order包含多条OrderDetail明细,每条OrderDetail明细都关联着一个Product,并且每个 Customer拥有一组相关联的Order。

LINQ to SQL能够让我们不论是在查询还是更新数据中都可以利用这些关系关联。例如,编写以下代码来创建一个新Product,并关联到一个数据库中已存在的“Beverages”Category上:

注意如何添加Product对象到该Category的Product集合中。这样就会指明这两个对象之间存在关系关联,并会导致LINQ to SQL在调用SubmitChange()时,自动维护两者之间的主/外键关系关联。

另一个LINQ to SQL有助于管理交叉表关系关联的例子,让我们看一下如何对一个现有的Customer创建一个新的Order。在设置Order的OrderDate和 RequireDate和Freight后,然后创建两个Customer订购的Product相关的OrderDetail,并添加到Order中,随 后关联Order到Customer上,最后更新所有变化回数据库:

正如所看到,执行所以这些工作的编程模型是十分清晰并且是面向对象的。

事务

事务是一种通过数据库(或其他资源管理器)提供的服务,来保证了一系列的单独的操作是原子性发生的——这就意味着它们要么全部成功,要么全部失败, 并且当这一系列操作都自动执行完毕之前,不会有任何更改会发生。当调用DataContext上的SumbitChange()方法时,这些更新操作会包 装到一个事务中。这就意味着当执行多个变化更新时,数据库永远不会陷入不一致的状态——这些变化要么一起被保存,要么任何变化都不保存。

验证和业务逻辑

对于处理数据,开发需要考虑的一件十分重要的事就是如何融合数据验证和业务规则逻辑。LINQ to SQL为开发者提供了多种途径,可以十分简洁地把这些整合到数据模型中。LINQ to SQL会确保一旦添加数据验证逻辑,就可以无论何时何地在都应用于数据模型上。这就避免了在多处的重复定义,保证了数据模型的可维护性和代码整洁。

构架验证支持

当在Visual Studio 2008中使用LINQ to SQL设计器定义数据模型类时,会被默认附加一些根据数据库表构架推断出的验证规则。数据模型类中的属性的数据类型会与数据库构架的数据类型相匹配。这就 意味着如果试图指定一个boolean值到decimal,或试图隐式转换numeric类型都会导致编译错误。如果数据库中的列可以为null,则通过 LINQ to SQL设计器创建的在数据模型中的相应的属性会是一个Nullable类型。如果试图给未标记为Nullable的属性指定null值,会自动引发异常。 相似地,LINQ to SQL也会确保数据库中的identity/unique列值的正确验证。

当然也可以使用LINQ to SQL设计器来覆写这些默认的构架驱动的验证设置——但是通过默认我们可以自动获得它们,而且不需要进行额外的工作。LINQ to SQL同样会自动处理转义的SQL值,这样就不必担心SQL注入攻击了。

自定义属性验证支持

构架驱动的数据验证仅仅是应用的第一步,但对于实际应用来说还是不够的。考虑Northwind中的一种情况——Customer类上的Phone属性,在数据库中被定义为NVARCHAR类型。开发者可以使用LINQ to SQL编写如下代码更新一个有效的电话号码:

但在应用中会碰到这样的疑问,如对于下面的代码,从单纯的SQL构架方面来说是合法的:

为防止虚假的电话号码被添加进数据库,我们可以添加一个自定义属性验证规则到Customer数据模型类中。使用局部类的特性,可以十分简单的添加规则来验证电话号码,只需要添加一个新的包含如下方法定义的局部类到我们的项目中:

以上代码利用了LINQ to SQL的两个特性:

1.所以通过LINQ to SQL设计器创建的类都被声明为局部类——这就意味着开发者可以十分方便地为这些类添加额外的方法,属性和事件。这样对通过LINQ to SQL设计器创建的数据模型类和DataContext类,可以很简单的扩充自已定义验证规则和额外的自定义辅助方法。没有任何设置或后续代码要求。

2.LINQ to SQL会在数据模型类和DataContext类中暴露了一些自定义的可扩展点,用来在事件发生之前和之后添加验证逻辑。其中许多的扩展点利用了称为“partial methods(局部方法)”的新语言特性。

在上面的验证示例中,我们使用了在任何设置Customer类上Phone属性时都会被执行的OnPhoneChanging方法。使用该方法来验 证输入,如果验证成功,则从该方法中返回并且LINQ to SQL会认定该值是有效的,否则就会在该验证方法中产生一个异常——防止发生赋值操作。

自定义实体对象验证支持

属性级别的验证对于验证数据模型类上独立的属性是十分有效的。但有时却需要同时验证一个对象上的多个属性。考虑这样一个场景,同时设置Order对象上的OrderDate和RequiredDate属性:

以上的代码从单纯的SQL构架方面来说是合法的——即使规定交货日期是订单下达日期的前一天是毫无意义的。好消息是现在在Beta2(.NET Framework 3.5)中LINQ to SQL可以十分简单地添加自定义实体级别的验证规则来防止类似的错误发生。可以为Order实体类添加一个局部类,并实现OnValidate()局部方 法,该方法会在实体的值将要记录进数据库的时候被调用。使用该验证方法可以访问和验证所有的数据模型类属性:

使用该验证方法我们可以检查实体类上的任何属性值(即使对于它的管理对象只获得只读访问),如果验证的值不正确就可以产生一个异常。从OnValidate()方法中产生的任何异常都导致从数据库更新操作中退出,并且回滚该操作所在事务中的所以更改。

自定义实体插入/更新/删除方法验证

在实际应用中,有时我们会需要对于特定的插入,更新或删除场景来添加验证逻辑。在Beta2(.NET Framework 3.5)中LINQ to SQL可以通过添加局部类型来扩展DataContext类,然后实现相应的局部方法来为数据模型实体自定义插入,更新和删除逻辑。当调用 DataContext类上的SubmitChanges()方法时,这些方法会被自动调用。

使用这些方法添加适当的验证逻辑后,如果验证通过就会通知LINQ to SQL继续进行数据库更新操作(通过调用DataContext类中的“ExecuteDynamicXYZ”方法):

适当地添加以上方法后,对于数据对象的任何创建/更新/删除操作都会自动调用这些方法。例如,考虑这样一个场景,创建一个新的Order并关联到一个已存在的Customer上:

当在上面的示例代码中调用northwind.SubmitChanges()时,LINQ to SQL会确认是否需要插入一个新的Order对象,并自动调用InsertOrder局部方法。

高级:为事务察看实体变化

在实际应用中,有时不能单纯地通过察看单独的插入/更新/插入操作来添加验证逻辑,而是应察看一个以事务发生的实体操作变化列表。从.NET Framework 3.5 Beta2开始,我们可以通过调用公共的DataContext.GetChangeSet()方法来访问这个变化列表。该方法会返回一个暴露每个已作出 的添加,修改和移除操作的ChangeSet对象。

还有一种可供选择的方式是编写DataContext的子类并覆写SubmitChanges()方法。然后就可以为更新操作检索ChangeSet,并执行任何自定义的数据验证:

使用乐观并发执行处理同时发生的变化

在多用户数据库系统中开发者需要考虑的事情之一,就是如何处理对于数据库中数据同时发生的更新。例如,假设两个用户在同一应用程序中检索同样的 Product对象,一个用户更新RecorderLevel为0,而另一个更新为1。如果两个用户都要试图保存Product的更新到数据库,那么开发 者就需要决定如何处理变化冲突。

一种方式是“让后来的更新者获胜”——这就意味者先来的用户提交的值会在重大用户没有察觉的情况下丢失。这通常被认为是一种缺乏应用程序开发经验的一种表现。

另一种而且是LINQ to SQL支持的方式是使用乐观并发执行模型——如何数据库中的原始值已经有其他更新操作事先要执行,LINQ to SQL会自动检测发生地点。LINQ to SQL可以提供一个更改值的冲突列表给开发者,并且能够调和分歧,或者是通过UI通知应用程序终端用户来让他们决定如何处理。

为插入/更新/删除场景使用存储过程或自定义SQL逻辑

对于数据库开发者来说,好消息是LINQ to SQL提供了相当灵活的开发模型,可以让开发者覆写通过LINQ to SQL自动执行的动态SQL,并替代为调用自定义的插入,更新,删除用的存储过程。

一开始的时候,我们可以定义数据模型并使用LINQ to SQL自动处理插入,更新,删除等逻辑。在稍后还可以自定义用于更新数据模型的存储过程或SQL——不需要对使用数据模型的应用程序逻辑作出任何改变,也 不需要对相应的数据验证或业务规则逻辑作出任何改变。这就为应用程序的构建提供了大量的灵活性。

总结

除了一般的插入,更新,删除操作,以及数据验证外,通过这篇Post我们还应注意以下一些要点:

1.善于利用表之间的关系关联进行数据更新

2.数据验证和业务逻辑验证的应用级别包括:构架级,实体级,属性级,更新操作时验证和以事务为单位的验证

3.LINQ to SQL还可以有效地处理SQL注入攻击

4.LINQ to SQL还可以自动处理事务

5.LINQ to SQL使用乐观并发执行模型处理更新冲突

LINQ to SQL更新数据库操作(转载)的更多相关文章

  1. MVC linq To SQL更新数据库操作

    首先在视图中提交数据,使用Html.BeginForm() @using(Html.BeginForm()) { @Html.EditorForModel() //编辑模板.控制器中传过来的数据 &l ...

  2. 【转】sql server数据库操作大全——常用语句/技巧集锦/经典语句

    本文为累计整理,有点乱,凑合着看吧! ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ☆ ☆ ☆ sql 宝 典 ☆ ☆ ☆ 2012年-8月 修订版 ☆ ...

  3. [LINQ TO SQL]使用LINQ TO SQL创建数据库

    这篇博客将介绍如何使用LINQ TO SQL来创建数据库,以及如何映射Table之间的主外键关系. 我们的数据库表关系如下: Province与City之间1:M,City与Area之间1:M的关系. ...

  4. MVC3+Linq to sql 显示数据库中数据表的数据

    1:首先创建asp.net mvc3应用程序 2:创建项目完成后 找到controllers文件鼠标右击选择添加控制器 3 为models文件夹添加一个linq to sql类文件,然后把数据库中的数 ...

  5. sql server数据库操作

    --插入整行数据 , '1983-08-29', 'A', 'A', 'A') --插入部分列数据 , '1983-08-29') --删除行记录 delete from person where n ...

  6. MySQL常用sql语句-----数据库操作

    在数据库操作中,操作基本都是围绕增删改查来操作.简称CRUD C创建创建 R读取/检索查询 U Update修改 D删除删除 在数操作数据库时,所有的数据库语句都要以分号结束 数据库操作不区分大小写 ...

  7. LINQ to SQL的CRUD操作

    创建数据对象模型 sqlmetal /code:"C:\MyProjects\VS2008\Data\LinqConsoleApp2\LinqConsoleApp2\northwnd.cs& ...

  8. R和python连接SQL sever 数据库操作

    在R的使用中,为了方便提取数据, 我们经常要进行数据库进行操作,接下来我们尝试使用R进行连接数据. 这里我们使用R中的RODBC进行操作, 首先,我们需要先配置ODBC资源管理器 通过任务管理器或者w ...

  9. SQL server 数据库 操作及简单查询

    使用SQL Sever语言进行数据库的操作 常用关键字identity 自增长primary key 主键unique 唯一键not null 非空references 外键(引用) 在使用查询操作数 ...

随机推荐

  1. Uedit的快捷键

    Key1 自动换行_CTRL + W     这个已经不是什么新奇的功能了,就连你们最不喜欢的notepad都有了这个功能.说来也奇怪,编辑器为什么都带有这个功能呢?谁愿意自己的编辑器带有水平滚动条啊 ...

  2. 记录毕业论文 LanguageTool 二次开发时用到的网站

    LanguageTool Development LanguageTool Supported Languages Share your knowledge about LT - LanguageTo ...

  3. 我的权限系统设计实现MVC4 + WebAPI + EasyUI + Knockout(三)图形化机构树

    一.前言 组织机构是国内管理系统中很重要的一个概念,以前我们基本都是采用数据列表的形式展现,最多只是采用树形列表展现.虽然够用,但是如果能做成图形化当然是最好不过了.这里我不用任何图形控件,就用最原始 ...

  4. ROM存储1/4周期正弦信号构造DDS

    上周的时候,老师让编写一个简单的dds程序,本文说明了整个过程中我遇到问题以及一些个人的思考.初次接触FPGA,如有问题请多多指教~ 1.几个疑问,解决和没有解决的. 为何采用ROM而不是直接采用DD ...

  5. 总结一下工作中遇到的NPOI以及在ASP.NET MVC中的使用

    1.前言 相信大家在工作中经常要遇到一些导入导出Execl操作.学习贵在分享,分享使人快乐,园子里的前辈已经有很多好的文章,鄙人也是能力有限,在这里把这些好的文章总结,方便以后再工作中使用. NPOI ...

  6. Command Pattern -- 命令模式原理及实现(C++)

    主要参考<大话设计模式>和<设计模式:可复用面向对象软件的基础>两本书.本文介绍命令模式的实现. What it is:Encapsulate a request as an ...

  7. windows API 开发飞机订票系统 图形化界面 (四)

    接下来的是录入航班.修改航班信息功能的实现: //录入航班 BOOL EntryFlight(HWND hEntryDlg){ TCHAR szDiscount[]; TCHAR szFare[],s ...

  8. CSS培训机构

    CSS培训机构[跑赢职场,跑赢未来] CSS培训机构[跑赢职场,跑赢未来]CSS设计热度白热化的今天,如何选对专业的CSS设计培训学校/机构,成为众多人关注的话题.跑赢职场就是css培训机构中的佼佼者 ...

  9. JavaEE EL的一些用法

    EL 可以在指示元素中设置EL是否使用 isELIgnored="true" true是不使用 也可以在web.xml中使用 <jsp-config> <jsp- ...

  10. java.lang.NoClassDefFoundError: javax/transaction/UserTransaction

    在运行定时任务的时候报错: Java.lang.NoClassDefFoundError: javax/transaction/UserTransaction 原因:缺少jta的jar包 解决方法:下 ...