您的位置:首页 > 数据库

(翻译) LINQ to SQL(Part 4 更新数据库) 自ScottGu

2007-10-08 18:53 621 查看
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.

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

Part 1: Introduction to LINQ to SQL

Part 2: Defining our Data Model Classes

Part 3: Querying our Database

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.

几个星期以来,我已经写了一系列关于LINQ to SQL的文章。LINQ to SQL.是一个.NET 3.5版本内建的对象关系映射框架,可以很方便的使用.NET 类为关系数据库建模。然后通过LINQ表达式来查询/更新/插入/删除数据。

以下是LINQ to SQL 系列的前三部分

Part 1: LINQ to SQL(Part 1介绍)

Part 2: (翻译) LINQ to SQL(Part 2 定义数据模型类)

Part 3: LINQ to SQL (Part 3 - 查询数据库)

今天我将介绍如何使用早前我们创建的数据模型,通过它来更新,插入,删除数据。同时我也会展示如何清晰地在我们的数据模型中集成业务逻辑及自定义验证逻辑。

Northwind Database Modeled using LINQ to SQL

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:

Northwind[u] LINQ to SQL数据库模型

[/u]

在此系列的 Part 2 演示了如何通过VS2008内建的LINQ to SQL设计器创建 LINQ to SQL 类模型。 以下是将在此篇文章中用到的Northwind示例数据库的类模型:

[u]

[/u]

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.

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).

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.

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

通过LINQ to SQL设计器我们定义了5个数据模型类:Product(产品), Category(类别), Customer(客户), Order(订单)和 OrderDetail(订单明细)。每个类的属性映射数据库中对应表的列。每个实体列的实例代表表中的一行。

在我们定义数据模型的时候,LINQ to SQL 设计器同时创建了用户的DataContext类来提供数据访问及修改的渠道。 在我们定义的数据模型里这个类命名为 "NorthwindDataContext".
NorthwindDataContext 类具有代表建模数据库中每个表[Product(产品), Category(类别), Customer(客户), Order(订单)的属性 。

如同在第三篇中所述,我们可以很方便的使用 LINQ 语法表达式,通过NorthwindDataContext
class来查询获取数据。 在执行时,LINQ to SQL将自动翻译LINQ查询表达式到适当的SQL代码 。

例如,如下LINQ表达式通过产品名称来获取一个产品对象。:



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()

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.


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.


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.

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

修改记录和 DataContext.SubmitChanges()

如以上示例,在执行查询及获取数据对象的时候, LINQ to SQL在默认情况下将记录任何将要应用于那些对象的改动或更新 。通过LINQ to SQL 的DataConext类我们可以作多个查询及修改,所有的修改都会被记录到一起:


注意:LINQ to SQL 修改记录发生在调用方 - 而不是在数据库. 这意味着并没有消耗任何数据库资源,也不需要在数据库中改变/安装任何软件。



在修改了数据对象之后,可以调用DataContext的"SubmitChanges()" 方法来应用改动到数据库。这将使LINQ to SQL动态计算和执行恰当的SQL代码来更新数据库。

例如,以下代码示例更新“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.

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

在调用northwind.SubmitChanges()的时候, LINQ to SQL将动态的创建和执行一个 SQL
"UPDATE" 语句来更新这两个产品属性。

如下代码对那些非流行,昂贵产品的"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.

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.

在调用 northwind.SubmitChanges() 的时候, LINQ to SQL将动态的创建和执行一个 SQL
"UPDATE" 语句来更新那些产品的ReorderLevel属性。

注意如果产品的属性值没有改变,那么此产品对象将会被认为没有变化,因此LINQ to SQL 将不会执行UPDATE 语句来更新数据库。 例如-如果"Chai"产品的单位价格已经是$2而且库存数量是4,调用SubmitChanges() 将不会执行任何数据库更新语句。反而仅仅在第二个例子中的ReorderLevel不是0的那些产品会被更新。

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.

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:

插入和删除的例子

除了更新数据库中的行之外,LINQ to SQL 同样可以插入和删除数据。 你可以在DataContext的表集合中增加/删除数据对象,然后调用 SubmitChanges()方法来实现。LINQ to SQL 将会记录这些增加/删除,在SubmitChanges() 被调用的时候,自动执行恰当的SQL INSERT 或 DELETE 语句。

插入一个新产品

通过创建一个新的“Product(产品)" 类实例来在数据库中增加一个新的产品,设置它的属性,然后加入DataContext的“Product(产品)集合:



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

在我们调用 "SubmitChanges()" 的时候,product 表中就会增加一行。

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:

删除产品

如同以上通过在DataContext的Product 集合增加一个产品对象来对数据库中插入一个产品,那么类似的,删除数据库中的一个产品就是在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查询获取了一系列不再继续订购,没有任何订单的产品,这些订单被传递到 DataContext类"Products"集合的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.

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这样的O/R映射,可以很方便为交叉表关系建立数据模型。例如,可以建立这样的模型:每个产品属于一个种类,每个订单包括订单的明细,每个订单明细关联到一个产品,每个客户拥有关联的订单集合。 在文章的第二部分已经讲述了如何建立数据模型及其之间的关系。

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()".

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.

注意以上我是如何将产品对象加入类别的产品集合的。这表明在这两个对象之间存在有关系,因此 在调用"SubmitChanges()"的时候LINQ to
SQL自动保持外键/主键关系。

另外一个例子是关于LINQ to SQL能够帮助管理交叉表关系以及简化我们的代码。我们看一下以下例子:唯一个已存在的客户创建一个新的订单。在设置递送时间及费用之后,创建两个订单的明细项目,将其关联到客户订购的产品。然后将订单关联的客户,更新数据库,保存所有的更新。



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.

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

事务

事务是数据库系统(或其他资源管理)提供系列操作完整性的服务 - 意味着所有的操作成功或者所有的操作失败,如果所有的操作失败,任何其他操作之前所有的操作将自动回滚。

在DataContext类调用 SubmitChanges()的时候,更新将被打包到一个事务中。 这样即使执行多个更新,数据库系统依然保持一致性。-或者所有的更改都被保存,或者一个都没有。

如果没有显示的定义事务范围, 调用SubmitChanges()的时候,LINQ to SQL DataContext 对象将自动启动一个数据库事务来指导更新。LINQ to SQL 允许显示的定义 TransactionScope 对象。这使得集成
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 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 支持多种方法在数据模型中集成验证和业务逻辑。

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.

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.

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.

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 将确保标识/唯一列被正确的赋值。

如果你愿意,你可以使用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:

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.

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.

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.

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

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

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

在以上验证的示例中,我使用 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.

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:

以上代码对于SQL数据库来说是合法的- 尽管将递送时间设置为订单时间的昨天是荒谬的。

幸好,在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.

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 Beta2 允许加入部分类来扩展DataContext类,通过实现部分方法来自定义数据模型实体的插入,更新和删除逻辑。这些方法将在调用 SubmitChanges() 的时候自动执行。

在这些方法中,你可以加入适当的验证逻辑。 - 如果验证逻辑通过,它将通知 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.

在调用l northwind.SubmitChanges() 时,, LINQ to SQL 将决定保存新的定单对象,r "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.

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:

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

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

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

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



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.

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.

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

乐观并发控制

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

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

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

在以后的随笔中我将介绍如何使用乐观并发

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

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?"

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.

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.

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

使用存储过程或者自定义SQL语句插入/更新删除

开发者(特别是DBA)常常习惯于写自定义的存储过程,在他们看到LINQ to SQL的时候,通常会问这样一个问题,“我如何完全控制这些生成的SQL语句的执行?。

LINQ to SQL 具有非常灵活的模型使得开发者可以覆写它自动执行的动态SQL,调用DBA定义的插入,修改及删除等存储过程。

在刚开始的时候,可以定义你的数据模型,让LINQ to SQL 自动管理插入,更新,删除的SQL逻辑。在以后的时间,你可以定义你的数据模型采用自己的存储过程或SQL语句-这不需要改变数据模型的任何应用逻辑,
也不需要改变任何验证的业务逻辑。这为构建你的应用提供了很大的灵活性。

在以后的日志中,我将讲述如何自定义你的数据模型来使用存储过程或自定义的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.

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.

总结

在使用LINQ to SQL 更新数据库、集成验证业务逻辑方面,希望以上能够给你一个很好的概览。 我想你会发现 LINQ to
SQL 能够大幅提高你处理数据的效率, 能够使你写出非常干净的面向对象的数据访问代码。

在后续的日志中,我将讲述.NET 3.5中新的 <asp:linqdatasource> 控件 , 讨论在ASP.NET中利用LINQ to SQL如何方便创建U。同时我将讲述LINQ to SQL 更特别的一些编程概念,包括乐观并发,懒惰和急切加载,表映射继承,自定义 SQL/SPROC 使用及更多相关内容。.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: