原贴链接:

http://weblogs.asp.net/scottgu/archive/2007/07/11/linq-to-sql-part-4-updating-our-database.aspx

 

Over the last few weeks I've been writing a series of blog posts that cover LINQ to SQL.  LINQ to SQL is a built-in O/RM (object relational mapper) that ships in the .NET Framework 3.5 release, and which enables you to easily model relational databases using .NET classes.  You can use LINQ expressions to query the database with them, as well as update/insert/delete data.

上个月我开始了一个讲解LINQ to SQL的帖子系列。LINQ to SQL是集成在.NET Framework3.5中的O/RM(对象关系映射)的实现,它让你非常容易地用.NET类来生成关系型数据库的模型。然后你可以用LINQ 表达式对它来进行查询,更新,插入删除。

Below are the first three parts of my LINQ to SQL series:

下边是我的前三篇的帖子的链接:

In today's blog post I'll cover how we we can use the data model we created earlier, and use it to update, insert, and delete data.  I'll also show how we can cleanly integrate business rules and custom validation logic with our data model.

在今天的帖子中,我将会讲解一下如何使用我们在前几篇帖子中生成数据模型,并且用它来更新、插入、删除数据。我还会展示一下如何将我们的业务规则和自定义的验证与我们的数据模型进行集成。



Northwind Database Modeled using LINQ to SQL

LINQ to SQL建成的Northwind数据库模型

 

In Part 2 of this series I walked through how to create a LINQ to SQL class model using the LINQ to SQL designer that is built-into VS 2008.  Below is a class model created for the Northwind sample database and which I'll be using in this blog post:

在本系列的第二部分(Part 2中我讲解了如何用内置在VS2008中的LINQ to SQL设计器来生成一个LINQ to SQL类模型。下边是用LINQ to SQL设计器生成的一个Northwind事例的模型,在本篇博客中将会用到它。

 

 

When we designed our data model using the LINQ to SQL data designer above we defined five data model classes: Product, Category, Customer, Order and OrderDetail.  The properties of each class map to the columns of a corresponding table in the database.  Each instance of a class entity represents a row within the database table.

在用LINQ to SQL数据设计器设计数据模型时,我们定义了一个数据模型类:Product,Category,Customer,OrderOrderDetail。类的属性映射到数据库相应的数据表的列上。每个类的实体代表了数据表的一条记录。

 

When we defined our data model, the LINQ to SQL designer also created a custom DataContext class that provides the main conduit by which we'll query our database and apply updates/changes.  In the example data model we defined above this class was named "NorthwindDataContext".  The NorthwindDataContext class has properties that represent each Table we modeled within the database (specifically: Products, Categories, Customers, Orders, OrderDetails).

当我们在定义数据模型时,LINQ to SQL设计器也自动生成了一个DataContext类,该类提供了我们查询数据库和提交更新及变更的一个主要通道。在我们上面定义的数据模型事例中,这个类的名字叫"NorthwindDataContext",NorthwindDataContext类含有代表了在数据库中我们建立模型的表的属性(具体来说就是:Product,Categories,Customers,Orders,OrderDetails)。

 

As I covered in Part 3 of this blog series, we can easily use LINQ syntax expressions to query and retrieve data from our database using this NorthwindDataContext class.  LINQ to SQL will then automatically translate these LINQ query expressions to the appropriate SQL code to execute at runtime.

在本系列的第3部分(Part 3)中我讲过,我们可以用这个NorthwindDataContext类通过方便地写LINQ语法表达式来对数据库进行查询和检索数据库。LINQ to SQL将会在运行时自动地将LINQ 表达式转换为适当的SQL语句。

 

For example, I could write the below LINQ expression to retrieve a single Product object by searching on the Product name:

例如,我可以写如下的LINQ 表达式来通过Product名称对产品查询出一个Product对象:

I could then write the LINQ query expression below to retrieve all products from the database that haven't yet had an order placed for them, and which also cost more than $100:

 

我可以写如下的LINQ 查询表达式来完成满足以下条件的查询:没有订单的,单价超过100美元的。

Note above how I am using the "OrderDetails" association for each product as part of the query to only retrieve those products that have not had any orders placed for them.

注意上面我是如何用每个产品的"OrderDetails"这个关联来查询的一部分,并通过它来查出那些尚未有订单的产品记录。

 

Change Tracking and DataContext.SubmitChanges()

变更跟踪和DataContext.SubmitChanges()方法

 

When we perform queries and retrieve objects like the product instances above, LINQ to SQL will by default keep track of any changes or updates we later make to these objects.  We can make any number of queries and changes we want using a LINQ to SQL DataContext, and these changes will all be tracked together. 

当查询并检索出像上边的Product实例的对象时,LINQ to SQL将会默认地保持着对该对象任何的我们对这些对象所做的变化或更新的跟踪。通过LINQ to SQLDataContext我们可以写许许多多的查询和更新,这些变化将会被保存在一起。

 

Note: LINQ to SQL change tracking happens on the consuming caller side - and not in the database.  This means that you are not consuming any database resources when using it, nor do you need to change/install anything in the database to enable it.

注意:LINQ to SQL的变化追踪只在调用端被保存――而不是在数据库端。这意味着在使用它时,你既不需要任何的数据库资源,也不需要在数据库中更改/安装任何的东西。

After making the changes we want to the objects we've retrieved from LINQ to SQL, we can then optionally call the "SubmitChanges()" method on our DataContext to apply the changes back to the database.  This will cause LINQ to SQL to dynamically calculate and execute the appropriate SQL code to update the database.

 

在对我们从LINQ to SQL中查询出来的对象进行了变化之后,我们可以选择调用DataContextSubmitChanges()方法来将更新返回给数据库。这将会导致LINQ to SQL动态地生成并执行适当的SQL语句来更新数据库。

For example, I could write the below code to update the price and # of units in stock of the "Chai" product in the database:

 

例如,我可以写如下的代码来更新数据库中的产品名称为"Chai"的产品的价格和存储数量:

When I call northwind.SubmitChanges() above, LINQ to SQL will dynamically construct and execute a SQL "UPDATE" statement that will update the two product property values we modified above.

在调用Northwindo.SubmitChanges()时,LINQ to SQL将会动态地构建LINQ to SQL语句并执行一个SQL语句中的"UPDATE"声明,该声明将会更新我们上面修改的两个属性。

 

I could then write the below code to loop over unpopular, expensive products and set the "ReorderLevel" property of them to zero:

 

然后我可以写如下的代码来通过遍历不受欢迎的,贵的产品,将它们的"ReorderLevel"属性设置为0

When I call northwind.SubmitChanges() above, LINQ to SQL will calculate and execute an appropriate set of UPDATE statements to modify the products who had their ReorderLevel property changed.

当我调用northwind.SubmitChange()方法时,LINQ to SQL将会生成并执行的将ReorderLevel属性变化的产品记录的相应字段更新的语句。

 

Note that if a Product's property values weren't changed by the property assignments above, then the object would not be considered changed and LINQ to SQL would therefore not execute an update for that product back to the database.  For example - if the "Chai" product's unitprice was already $2 and the number of units in stock was 4, then calling SubmitChanges() would not cause any database update statements to execute.  Likewise, only those products in the second example whose ReorderLevel was not already 0 would be updated when the SubmitChanges() method was called.

 

注意,如果一个产品的属性值没有被上边的属性声明给更改,那个这个对象将不会被认为被更改过了,LINQ to SQL也因此不会为那条产品到数据库中执行一条Update语句。例如,如果"Chai"产品 的单价已经是2美元,并且库存数量也是4,那么调用SubmitChanges()方法将不会执行任何的Update语句。同样的,第2个事例中,只有那些ReorderLevel还不是0的产品才会在调用SubmitChange()方法时被更新。

 

Insert and Delete Examples

插入和删除事例

 

In addition to updating existing rows in the database, LINQ to SQL obviously also enables you to insert and delete data.  You can accomplish this by adding/removing data objects from the DataContext's table collections, and by then calling the SubmitChanges() method.  LINQ to SQL will keep track of these additions/removals, and automatically execute the appropriate SQL INSERT or DELETE statements when SubmitChanges() is invoked.

 

除了允许你更新在数据库已有的数据记录之后,LINQ to SQL显然也允许你向数据库中插入和删除数据库。你可以通过在DataContext的表集合中添加/删除对象,然后调用SubmitChanges()方法来完成对数据插入和删除。LINQ to SQL将会跟踪这些添加和删除的动作,并且当SubmiChanges()被触发时执行适当的InsertDeleteSQL语句。

Inserting a New Product

插入一条新产品

I can add a new product to my database by creating a new "Product" class instance, setting its properties, and then by adding it to my DataContext's "Products" collection:

 

我可以通过如下方式来向数据库中添加一条新的产品记录:生成一个新的"Product"类的实例,设置其属性,然后将它添加到DataContext"Product"集合中:

When we call "SubmitChanges()" above a new row will be created in our products table.

然后调用上面的SubmitChanges()方法时,一条新记录将会添加到Products数据表中。

 

Deleting Products

删除产品记录

 

Just as I can express that I want to add a new Product to the database by adding a Product object into the DataContext's Products collection, I can likewise express that I want to delete a product from a database by removing it from the DataContext's Products collection:

就像上面我可以通过将一个Product对象添加到DataContextProducts集合中来实现添加一条记录到数据库中那样,我同样也可以通过从DataContext的产品集合中移除一个Product对象来完成对数据库中记录的删除:

 

Note above how I'm retrieving a sequence of discontinued products that no one has ever ordered using a LINQ query, and then passing it to the RemoveAll() method on my DataContext's "Products" collection.  When we call "SubmitChanges()" above all of these Product rows will be deleted from our products table.

 注意上面我用LINQ查询来检索出一个不再出售的,订单数量为0的产品结果集,然后将它传到DataContextProducts集合的RemoveAll()方法中。当我们调用 SubmitChanges()访求时,所有的这些记录将会从数据库中删除。

 

Updates across Relationships

通过关系进行更新

 

What makes O/R mappers like LINQ to SQL extremely flexible is that they enable us to easily model cross-table relationships across our data model.  For example, I can model each Product to be in a Category, each Order to contain OrderDetails for line-items, associate each OrderDetail line-item with a Product, and have each Customer contain an associated set of Orders.  I covered how to construct and model these relationships in Part 2 of this blog series.

使得O/R映射器,比如LINQ to SQL,特别灵活的是它们允许我们非常方便地通过我们的数据模型来对交叉的表间关系进行建模。例如,我可以将每个Product放到一个Category中,每条Order可以包含OrderDetails,将每个OrderDetail的数据项跟产品关联起来,每个有一套订单。在本系列的第二部分(Part 2)我讲解了如何组织并生成这些关系。

 

LINQ to SQL enables me to take advantage of these relationships for both querying and updating my data. For example, I could write the below code to create a new Product and associate it with an existing "Beverages" category in my database like so:

 

LINQ to SQL使得我在查询和更新我的数据时均可以使用这些关系。例如,我可以写如下的代码来生成一条新产品记录,并将它与在数据库中已经存在的"Beverages"类别关联起来:

Note above how I'm adding the Product object into the Category's Products collection.  This will indicate that there is a relationship between the two objects, and cause LINQ to SQL to automatically maintain the foreign-key/primary key relationship between the two when I call "SubmitChanges()".

注意上面我如何将一个Product对象添加到类别的Products集合中。这表明了在两个对象之间存在着关系,并且使得在调用SubmitChanges()方法时LINQ to SQL自动地维护外键/主键关系。

 

For another example of how LINQ to SQL can help manage cross-table relationships for us and help clean up our code, let's look at an example below where I'm creating a new Order for an existing customer.  After setting the required ship date and freight costs for the order, I then create two order line-item objects that point to the products the customer is ordering.  I then associate the order with the customer, and update the database with all of the changes.

另外一个关于LINQ to SQL如何帮助我们管理表间交叉的关系并且使得我们的代码更清洁的例子,让我们看一下下面的一个为已经存在的客户生成一条订单的事例。在设置了请求的时间和订单的运费之后,我生成了两个指向客户订下的产品的Order对象。然后将这个订单和客户关联起来,并且将所有的这些变更更新至数据库。

 

As you can see, the programming model for performing all of this work is extremely clean and object oriented. 

正如你看到的,实现所有这些工作的编程模型特别的简单,并且是面向对象的。

 

Transactions

 

事务

 

A transaction is a service provided by a database (or other resource manager) to guarantee that a series of individual actions occur atomically - meaning either they all succeed or they all don't, and if they don't then they are all automatically undone before anything else is allowed to happen.

 

事务是数据库(或者其他的资源管理器)提供的一种服务,该服务能保证一系列单独的行为自动的触发――也就是要么它们全部成功,要么就不成功,如果不成功的话,它们将会在允许做其他事情之前自动地回滚。

 

When you call SubmitChanges() on your DataContext, the updates will always be wrapped in a Transaction.  This means that your database will never be in an inconsistent state if you perform multiple changes - either all of the changes you've made on your DataContext are saved, or none of them are.

 

当你调用DataContextSubmictChanges()方法时,更新部分总是会被包装在一个事务中。这意味着如果你执行了多步变更的话,你的数据库永远不会处于不一致的情况――要么将你所有对DataContext做的变化保存至数据库,要么全不保存。

 

If no transaction is already in scope, the LINQ to SQL DataContext object will automatically start a database transaction to guard updates when you call SubmitChanges(). Alternatively, LINQ to SQL also enables you to explicitly define and use your own TransactionScope object (a feature introduced in .NET 2.0).  This makes it easier to integrate LINQ to SQL code with existing data access code you already have.  It also means that you can enlist non-database resources into the transaction - for example: you could send off a MSMQ message, update the file-system (using the new transactional file-system support), etc - and scope all of these work items in the same transaction that you use to update your database with LINQ to SQL.

 

如果没有已经排除的事务,LINQ to SQL DataContext将会在调用SubmitChanges()方法时自动地开启一个事务来进行更新。另外,LINQ to SQL也允许你显示地声明并使用你自己的事务处理对象(在.Net2.0中介绍的一个特性)。这使得将LINQ to SQL代码和现有的数据访问代码集成变得更加容易。也意味着你可以将一个非数据库资源添加到数据库中――例如,你可以发送一条MSMQ消息,更新文件系统(用新的事务文件系统支持)等――并且将所有的这些工作放到同你用LINQ to SQL更新你数据库的一个事务中。

Validation and Business Logic

验证和业务逻辑

 

One of the important things developers need to think about when working with data is how to incorporate validation and business rule logic.  Thankfully LINQ to SQL supports a variety of ways for developers to cleanly integrate this with their data models. 

开发者在跟数据打交道时需要考虑的一个重要的事情就是如何将验证和业务逻辑结合起来。幸运的是,LINQ to SQL支持开发者清晰地将它们集成在数据模型中的各种各样的方法。

LINQ to SQL enables you to add this validation logic once - and then have it be honored regardless of where/how the data model you've created is used.  This avoids you having to repeat logic in multiple places, and leads to a much more maintainable and clean data model. 

 

LINQ to SQL使得你添加一次这些验证逻辑――然后你就可以不用管你生成的数据模型如何被使用,也不用管在何处被使用。这避免了你在我处来重复你的验证规则,而且使得数据模型更具有可维护性和简洁性。

 

Schema Validation Support

架构验证的支持

When you define your data model classes using the LINQ to SQL designer in VS 2008, they will by default be annotated with some validation rules inferred from the schema of the tables in the database.

当使用VS2008中的LINQ to SQL设计器来定义数据模型为时,它们会被默认地加上从数据表中反映出来的验证规则。

 

The datatypes of the properties in the data model classes will match the datatypes of the database schema.  This means you will get compile errors if you attempt to assign a boolean to a decimal value, or if you attempt to implicitly convert numeric types incorrectly.

数据模型类中的属性的数据类型要和数据库中的数据项的数据类型相一致。这意味着如果你试图将一个boolean类型赋值给一个decimal类型的值,或者错误的隐示地转换一个数据类型时,你就会得到一个编译错误。

If a column in the database is marked as being nullable, then the corresponding property in the data model class created by the LINQ to SQL designer will be a nullable type.  Columns not marked as nullable will automatically raise exceptions if you attempt to persist an instance with a null value.  LINQ to SQL will likewise ensure that identity/unique column values in the database are correctly honored.

如果数据库中的一列被标志为可空,那么数据模型类相应的属性将是一个可空的类型。如果你试图对没有被标为可空的列赋空值,将会自动抛出异常。 LINQ to SQL 将同样确保标识/唯一列被正确的赋值。

You can obviously use the LINQ to SQL designer to override these default schema driven validation settings if you want - but by default you get them automatically and don't have to take any additional steps to enable them.  LINQ to SQL also automatically handles escaping SQL values for you - so you don't need to worry about SQL injection attacks when using it.

如果你乐意的话,你可以使用LINQ to SQL 设计器覆盖默认的框架验证设置。但是在默认情况下,这是自动的并不需要额外的步骤来启用它。LINQ to SQL 也会为你自动管理SQL语句-所以在使用时你不必担心SQL注入。

 

Custom Property Validation Support

自定义属性验证支持

Schema driven datatype validation is useful as a first step, but usually isn't enough for real-world scenarios. 

数据库框架验证作为第一步非常有用,但是在实际的场景中并不足够。

Consider for example a scenario with our Northwind database where we have a "Phone" property on the "Customer" class which is defined in the database as an nvarchar.  Developers using LINQ to SQL could write code like below to update it using a valid telephone number: 

例如考虑这一场景,"Customer"类有一个"phone"的属性,被定义为NVarchar类型,开发者编写如下代码,用一个合法的电话号码来对它进行更新:

The challenge that we will run into with our application, however, is that the below code is also legal from a pure SQL schema perspective (because it is still a string even though it is not a valid phone number):

然而,这种更新在程序中是行得能的,从SQL语句上来说,如下代码依然是合法的(因为它依然是一个字符串,虽然不是一个电话号码)

To prevent bogus phone numbers from being added into our database, we can add a custom property validation rule to our Customer data model class.  Adding a rule to validate phone numbers using this feature is really easy.  All we need to-do is to add a new partial class to our project that defines the method below:

为避免错误的号码插入到数据库中,我们可以向Customer数据类型类中加入自定义的属性验证规则。用这个特性来添加一条对电话号码的验证规则确实非常简单。我们所需要做的是在项目中加一个新的部分类来定义以下方法。:

 

The code above takes advantage of two characteristics of LINQ to SQL:

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

1) All classes created by the LINQ to SQL designer are declared as "partial" classes - which means that developers can easily add additional methods, properties, and events to them (and have them live in separate files).  This makes it very easy to augment the data model classes and DataContext classes created by the LINQ to SQL designer with validation rules and additional custom helper methods that you define.  No configuration or code wire-up is required.

1) LINQ to SQL 设计器生成的类都被声明为"局部"类 -这意味着开发者可以向这些总局类中很方便的增加方法,属性,及事件。因此验证规则和用户自定义的辅助方法可以很方便的加入数据模型类和DataContext类中。不需要设置或者代码绑定。

 

2) LINQ to SQL exposes a number of custom extensibility points in its data model and DataContext classes that you can use to add validation logic before and after things take place.  Many of these extensibility points utilize a new language feature called "partial methods" that is being introduced with VB and C# in VS 2008 Beta2.  Wes Dyer from the C# team has a good explanation of how partial methods works in this blog post here.

2) LINQ to SQL 揭示了数据模型类及DataContext类中很多用户可扩展的地方,在这些地方可以添加验证逻辑。可扩展的地方利用了一个新的语言特性,称之为“部分方法”,这是VS2008Beta2 VB和C#引入的。Wes Dyer 在他的日志中对“部分方法”是如何工作的有很好的解释(here.)。

 

In my validation example above, I'm using the OnPhoneChanging partial method that is executed anytime someone programmatically sets the "Phone" property on a Customer object.  I can use this method to validate the input however I want (in this case I'm using a regular expression).  If everything passes successfully, I just return from the method and LINQ to SQL will assume that the value is valid.  If there are any issues with the value, I can raise an exception within the validation method - which will prevent the assignment from taking place.

在以上验证的示例中,我使用 OnPhoneChanging 部分方法,此方法将在程序设置“Customer”对象的“Phone”属性时执行。 如果我想的话我可以使用这个方法来验证输入—(在此使用正则表达式)如果一切正确,将从此方法返回而且LINQ to SQL 将认为该值合法。如果有什么错误发生,在验证方法中抛出一个异常-这将阻止赋值。

Custom Entity Object Validation Support

自定义实体对象验证支持

 

Property level validation as used in the scenario above is very useful for validating individual properties on a data model class.  Sometimes, though, you want/need to validate multiple property values on an object against each other. 

以上场景中的属性级验证对验证数据模型类的彼此独立的属性非常有用。有时,你需要验证互相作用的多个属性的值。

Consider for example a scenario with an Order object where you set both the "OrderDate" and the "RequiredDate" properties:

例如,设置订单对象的 "OrderDate" 和 "RequiredDate" 属性:

 

The above code is legal from a pure SQL database perspective - even though it makes absolutely no sense for the required delivery date of the new order to be entered as yesterday. 

上面代码对于SQL数据库来说是合法的- 尽管将传递的时间设置为订单时间的昨天是没有任何意义的。

The good news is that LINQ to SQL in Beta2 makes it easy for us to add custom entity level validation rules to guard against mistakes like this from happening.  We can add a partial class for our "Order" entity and implement the OnValidate() partial method that will be invoked prior to the entity's values being persisted into the database.  Within this validation method we can then access and validate all of the data model class properties:

幸好,在LINQ to SQLBeta2 版本中,通过增加自定义实体级验证规则可以防止此类错误的发生。我们可以给“Order”实体增加一个部分类并且实现OnValidate()的部分方法, 此方法将在实体值被保存在数据库中之前调用。在此验证方法中我们可以访问和验证数据模型类所有的属性。

Within this validation method I can check any of the entity's property values (and even obtain read-only access to its associated objects), and raise an exception as needed if the values are incorrect.  Any exceptions raised from the OnValidate() method will abort any changes from being persisted in the database, and rollback all other changes in the transaction.

在验证方法中可以检查实体的属性值(甚至只读访问其关联的对象),如果值不合法的话将抛出异常。任何抛出的异常将中止保存到数据库,并且回滚同一事务中其他的改动。

Custom Entity Insert/Update/Delete Method Validation

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

 There are times when you want to add validation logic that is specific to insert, update or delete scenarios.  LINQ to SQL in Beta2 enables this by allowing you to add a partial class to extend your DataContext class and then implement partial methods to customize the Insert, Update and Delete logic for your data model entities.  These methods will be called automatically when you invoke SubmitChanges() on your DataContext.
  经常你需要的验证逻辑不单单是在独立的插入/更新/删除操作中。LINQ to SQL Beta2允许你将“局部方法”添加到DataContext类中来为你的添加更新和删除逻辑添加自定义的验证。这些方法在调用SubmitChanges()时将会被自动调用。
You can add appropriate validation logic within these methods - and if it passes then tell LINQ to SQL to continue with persisting the relevant changes to the database (by calling the DataContext's "ExecuteDynamicXYZ" method):

在这些方法中,你可以加入适当的验证逻辑。 - 如果验证逻辑通过,它将通知 LINQ to SQL保存相关的改动到数据库。 (通过调用DataContext的"ExecuteDynamicXYZ" 方法):

What is nice about adding the above methods is that the appropriate ones are automatically invoked regardless of the scenario logic that caused the data objects to be created/updated/deleted.  For example, consider a simple scenario where we create a new Order and associate it with an existing Customer:

一个比较好的地方是,以上方法在数据对象创建/更新/删除时自动匹配执行。例如,如下示例, 我们创建一个新的定单关联到一个存在的客户。


When we call northwind.SubmitChanges() above, LINQ to SQL will determine that it needs to persist a new Order object, and our "InsertOrder" partial method will automatically be invoked. 

在我们调用Northwind.SubmitChanges() 时,, LINQ to SQL 将决定保存新的定单对象, "InsertOrder"部分方法将被自动调用。


Advanced: Looking at the Entire Change List for the Transaction

高级:事务中全部的发动列表

There are times when adding validation logic can't be done purely by looking at individual insert/update/delete operations - and instead you want to be able to look at the entire change list of operations that are occurring for a transaction. 

经常你需要的验证逻辑不单单是在独立的插入/更新/删除操作中。反而,你需要检查在同一事务中发生的所有改动。

Starting with Beta2 of .NET 3.5, LINQ to SQL now enables you to get access to this change list by calling the public DataContext.GetChangeList() method.  This will return back a ChangeList object that exposes collections of each addition, removal and modification that has been made. 

.NET 3.5 Beta2,LINQ to SQL开始,你可以通过调用DataContext.GetChangeList() 访问所有的改变列表。此方法返回一个ChangeList 对象,该对象包含了增加,删除及修改的集合。


One approach you can optionally employ for advanced scenarios is to sub-class the DataContext class and override its SubmitChange() method.  You can then retrieve the ChangeList() for the update operation and perform any custom validation you want prior to executing it:

在更高级的场景中,你可以继承DataContext类,重写SubmitChange()方法。在保存到数据库之前,通过获取更新操作的ChangeList()进行自定义的验证
 

The above scenario is a somewhat advanced one - but it is nice to know that you always have the ability to drop-down and take advantage of it if needed.
以上是一个高级的场景--但是最好你要在需要的时候 ,你可以实现并能利用它。


Handling Simultaneous Changes with Optimistic Concurrency

乐观并发控制


One of the things that developers need to think about in multi-user database systems is how to handle simultaneous updates of the same data in the database.  For example, assume two users retrieve a product object within an application, and one of the users changes the ReorderLevel to 0 while the other changes it to 1.  If both users then attempt to save the product back to the database, the developer needs to decide how to handle the change conflicts. 

开发者需要关心的一点是,在多用户的数据库系统中,如何处理同一数据同时更新。例如,假定两个用在以各应用中获取一个产品对象,其中一个用户设置RecorderLevel为0,而另外一个用户设置为1。如果两个用户试图将此产品保存到数据库,开发者需要决定如何处理这个改动的冲突。

 One approach is to just "let the last writer win" - which means that the first user's submitted value will be lost without the end-users realizing it.  This is usually considered a poor (and incorrect) application experience. 

一种解决方法是 "最后写入者赢" - 这意味着第一位用户没有的到提示的情况下,其提交的值将被丢掉。通常这被认为是一个不好(不正确)的应用经验。

Another approach which LINQ to SQL supports is to use an optimistic concurrency model - where LINQ to SQL will automatically detect if the original values in the database have been updated by someone else prior to the new values being persisted.  LINQ to SQL can then provide a conflict list of changed values to the developer and enable them to either reconcile the differences or provide the end-user of the application with UI to indicate what they want to-do. 

另外一个方法是 LINQ to SQL 支持乐观并发模型。 -  在保存新值之前,LINQ to SQL 将自动探测原值已被其他人修改.  LINQ to SQL 然后可以提供一个改变值得冲突列表,这样开发者或者协调数值之间的差距,或者在UI中提示用户要如何处理。

I'll cover how to use optimistic concurrency with LINQ to SQL in a future blog post.

在以后的帖子中我将讲解如何用LINQ to SQL处理乐观并发冲突。


Using SPROCs or Custom SQL Logic for Insert/Update/Delete Scenarios

用存储过程或者自定义的SQL语句来插入/更新/删除记录的情景

 

One of the questions that developers (and especially DBAs) who are used to writing SPROCs with custom SQL usually ask when seeing LINQ to SQL for the first time is - "but how can I have complete control of the underlying SQL that is executed?" 

 

那些过去用SQL语句写自定义的存储过程(尤其DBA)在第一次见到LINQ to SQL时经常问的一个问题是—"可是我如何完全地控制它执行的SQL语句?"

 

The good news is that LINQ to SQL has a pretty flexible model that enables developers to override the dynamic SQL that is automatically executed by LINQ to SQL, and instead call custom insert, update, delete SPROCs that they (or a DBA) define themselves. 

 

有一个好的消息,就是LINQ to SQL有一个非常之灵活的模型,该模型允许开发者们重写LINQ to SQL动态生成的SQL语句,用他们自定义的插入/更新/删除的存储过程来替代那些生成的SQL语句.

 

What is really nice is that you can start off by defining your data model and have LINQ to SQL automatically handle the insert, update, delete SQL logic for you.  You can then at a later point customize the data model to use your own custom SPROCs or SQL for updates - without having to change any of the application logic that is using your data model, nor would you have to change any of the validation or business rules logic supporting it (all of this stays the same).  This provides a lot of flexibility in how you build your application.

 

真正好的一点是你可以通过定义你的数据模型来让LINQ to SQL自动的处理插入/更新/删除的SQL逻辑。你可以为更新定义一个你自己的存储过程或者SQL语句-这样在以后更新应用程序时你可以既不必去更改应用了你的数据模型的应用程序的逻辑,又不必去更改任何的验证或者业务逻辑(所有的这些使用原有的即可)。这在你如何构建应用程序上提供了很大的灵活性。

 

I'll cover how to customize your data models to use SPROCs or custom SQL in a future blog post.

在接下来的一篇帖子中我将会讲解一下如何自定义你的数据模型来使用存储过程或者自定义的SQL语句。

 

 

Summary

 

总结

 

Hopefully the above post provides a good summary of how you can easily use LINQ to SQL to update your database, and cleanly integrate validation and business logic with your data models.  I think you'll find that LINQ to SQL can dramatically improve your productivity when working with data, and enable you to write extremely clean object-oriented data access code.

 

希望上面这篇帖子给你提供了如何用LINQ to SQL方便地更新你的数据库的,如何清晰地将你的验证及业务逻辑和你的数据模型结合起来的一个好的概述。我想你会发现,在和数据打交道时,LINQ to SQL会极大地提高你的生成力,并且能够让你写出非常整洁的面向对象的数据访问的代码。

 

In upcoming blog posts in this series I'll cover the new <asp:linqdatasource> control coming in .NET 3.5, and talk about how you can easily build data UI in ASP.NET that takes advantage of LINQ to SQL data models. I'll also cover some more specific LINQ to SQL programming concepts including optimistic concurrency, lazy and eager loading, table mapping inheritance, custom SQL/SPROC usage, and more.

 

在本系列的下面的帖子中,我将讲述一下在.Net3.5中的新增的<asp:linqdatasource>控件,并且讲一下在使用LINQ to SQL的数据模型的情况下在ASP.NET中建立一个数据的UI是多么地方便!我会更近一步地讲术一下LINQ to SQL的编程思想,包括优化并发冲突,延迟和提前加载,表映射的继承,自定义的存储过程的使用等。

Hope this helps,

希望这些能对你有所帮助

Scott

posted on 2007-11-19 18:31  是谁啊?  阅读(3778)  评论(11编辑  收藏  举报