ScottGu之博客翻译-LINQ to SQL第四部分,更新数据库 LINQ to SQL (Part 4 - Updating our Database)...
原貼鏈接:
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.
上個(gè)月我開(kāi)始了一個(gè)講解LINQ to SQL的帖子系列。LINQ to SQL是集成在.NET Framework3.5中的O/RM(對(duì)象關(guān)系映射)的實(shí)現(xiàn),它讓你非常容易地用.NET類(lèi)來(lái)生成關(guān)系型數(shù)據(jù)庫(kù)的模型。然后你可以用LINQ 表達(dá)式對(duì)它來(lái)進(jìn)行查詢,更新,插入刪除。
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.
在今天的帖子中,我將會(huì)講解一下如何使用我們?cè)谇皫灼又猩蓴?shù)據(jù)模型,并且用它來(lái)更新、插入、刪除數(shù)據(jù)。我還會(huì)展示一下如何將我們的業(yè)務(wù)規(guī)則和自定義的驗(yàn)證與我們的數(shù)據(jù)模型進(jìn)行集成。
Northwind Database Modeled using LINQ to SQL
用LINQ to SQL建成的Northwind數(shù)據(jù)庫(kù)模型
?
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)中我講解了如何用內(nèi)置在VS2008中的LINQ to SQL設(shè)計(jì)器來(lái)生成一個(gè)LINQ to SQL類(lèi)模型。下邊是用LINQ to SQL設(shè)計(jì)器生成的一個(gè)Northwind事例的模型,在本篇博客中將會(huì)用到它。
?
?
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數(shù)據(jù)設(shè)計(jì)器設(shè)計(jì)數(shù)據(jù)模型時(shí),我們定義了一個(gè)數(shù)據(jù)模型類(lèi):Product,Category,Customer,Order和OrderDetail。類(lèi)的屬性映射到數(shù)據(jù)庫(kù)相應(yīng)的數(shù)據(jù)表的列上。每個(gè)類(lèi)的實(shí)體代表了數(shù)據(jù)表的一條記錄。
?
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).
當(dāng)我們?cè)诙x數(shù)據(jù)模型時(shí),LINQ to SQL設(shè)計(jì)器也自動(dòng)生成了一個(gè)DataContext類(lèi),該類(lèi)提供了我們查詢數(shù)據(jù)庫(kù)和提交更新及變更的一個(gè)主要通道。在我們上面定義的數(shù)據(jù)模型事例中,這個(gè)類(lèi)的名字叫"NorthwindDataContext",NorthwindDataContext類(lèi)含有代表了在數(shù)據(jù)庫(kù)中我們建立模型的表的屬性(具體來(lái)說(shuō)就是: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)中我講過(guò),我們可以用這個(gè)NorthwindDataContext類(lèi)通過(guò)方便地寫(xiě)LINQ語(yǔ)法表達(dá)式來(lái)對(duì)數(shù)據(jù)庫(kù)進(jìn)行查詢和檢索數(shù)據(jù)庫(kù)。LINQ to SQL將會(huì)在運(yùn)行時(shí)自動(dòng)地將LINQ 表達(dá)式轉(zhuǎn)換為適當(dāng)?shù)?/span>SQL語(yǔ)句。
?
For example, I could write the below LINQ expression to retrieve a single Product object by searching on the Product name:
例如,我可以寫(xiě)如下的LINQ 表達(dá)式來(lái)通過(guò)Product名稱對(duì)產(chǎn)品查詢出一個(gè)Product對(duì)象:
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:
?
我可以寫(xiě)如下的LINQ 查詢表達(dá)式來(lái)完成滿足以下條件的查詢:沒(méi)有訂單的,單價(jià)超過(guò)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.
注意上面我是如何用每個(gè)產(chǎn)品的"OrderDetails"這個(gè)關(guān)聯(lián)來(lái)查詢的一部分,并通過(guò)它來(lái)查出那些尚未有訂單的產(chǎn)品記錄。
?
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.?
當(dāng)查詢并檢索出像上邊的Product實(shí)例的對(duì)象時(shí),LINQ to SQL將會(huì)默認(rèn)地保持著對(duì)該對(duì)象任何的我們對(duì)這些對(duì)象所做的變化或更新的跟蹤。通過(guò)LINQ to SQL的DataContext我們可以寫(xiě)許許多多的查詢和更新,這些變化將會(huì)被保存在一起。
?
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的變化追蹤只在調(diào)用端被保存――而不是在數(shù)據(jù)庫(kù)端。這意味著在使用它時(shí),你既不需要任何的數(shù)據(jù)庫(kù)資源,也不需要在數(shù)據(jù)庫(kù)中更改/安裝任何的東西。
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.
?
在對(duì)我們從LINQ to SQL中查詢出來(lái)的對(duì)象進(jìn)行了變化之后,我們可以選擇調(diào)用DataContext的SubmitChanges()方法來(lái)將更新返回給數(shù)據(jù)庫(kù)。這將會(huì)導(dǎo)致LINQ to SQL動(dòng)態(tài)地生成并執(zhí)行適當(dāng)?shù)?/span>SQL語(yǔ)句來(lái)更新數(shù)據(jù)庫(kù)。
For example, I could write the below code to update the price and?# of units in?stock?of the "Chai" product in the database:
?
例如,我可以寫(xiě)如下的代碼來(lái)更新數(shù)據(jù)庫(kù)中的產(chǎn)品名稱為"Chai"的產(chǎn)品的價(jià)格和存儲(chǔ)數(shù)量:
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.
在調(diào)用Northwindo.SubmitChanges()時(shí),LINQ to SQL將會(huì)動(dòng)態(tài)地構(gòu)建LINQ to SQL語(yǔ)句并執(zhí)行一個(gè)SQL語(yǔ)句中的"UPDATE"聲明,該聲明將會(huì)更新我們上面修改的兩個(gè)屬性。
?
I could then write the below code to loop over unpopular, expensive products and set the "ReorderLevel" property of them to zero:
?
然后我可以寫(xiě)如下的代碼來(lái)通過(guò)遍歷不受歡迎的,貴的產(chǎn)品,將它們的"ReorderLevel"屬性設(shè)置為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.
當(dāng)我調(diào)用northwind.SubmitChange()方法時(shí),LINQ to SQL將會(huì)生成并執(zhí)行的將ReorderLevel屬性變化的產(chǎn)品記錄的相應(yīng)字段更新的語(yǔ)句。
?
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.
?
注意,如果一個(gè)產(chǎn)品的屬性值沒(méi)有被上邊的屬性聲明給更改,那個(gè)這個(gè)對(duì)象將不會(huì)被認(rèn)為被更改過(guò)了,LINQ to SQL也因此不會(huì)為那條產(chǎn)品到數(shù)據(jù)庫(kù)中執(zhí)行一條Update語(yǔ)句。例如,如果"Chai"產(chǎn)品 的單價(jià)已經(jīng)是2美元,并且?guī)齑鏀?shù)量也是4,那么調(diào)用SubmitChanges()方法將不會(huì)執(zhí)行任何的Update語(yǔ)句。同樣的,第2個(gè)事例中,只有那些ReorderLevel還不是0的產(chǎn)品才會(huì)在調(diào)用SubmitChange()方法時(shí)被更新。
?
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.
?
除了允許你更新在數(shù)據(jù)庫(kù)已有的數(shù)據(jù)記錄之后,LINQ to SQL顯然也允許你向數(shù)據(jù)庫(kù)中插入和刪除數(shù)據(jù)庫(kù)。你可以通過(guò)在DataContext的表集合中添加/刪除對(duì)象,然后調(diào)用SubmitChanges()方法來(lái)完成對(duì)數(shù)據(jù)插入和刪除。LINQ to SQL將會(huì)跟蹤這些添加和刪除的動(dòng)作,并且當(dāng)SubmiChanges()被觸發(fā)時(shí)執(zhí)行適當(dāng)?shù)?/span>Insert或Delete的SQL語(yǔ)句。
Inserting a New Product
插入一條新產(chǎn)品
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:
?
我可以通過(guò)如下方式來(lái)向數(shù)據(jù)庫(kù)中添加一條新的產(chǎn)品記錄:生成一個(gè)新的"Product"類(lèi)的實(shí)例,設(shè)置其屬性,然后將它添加到DataContext的"Product"集合中:
When we call "SubmitChanges()" above a new row will be created in our products table.
然后調(diào)用上面的SubmitChanges()方法時(shí),一條新記錄將會(huì)添加到Products數(shù)據(jù)表中。
?
Deleting Products
刪除產(chǎn)品記錄
?
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:
就像上面我可以通過(guò)將一個(gè)Product對(duì)象添加到DataContext的Products集合中來(lái)實(shí)現(xiàn)添加一條記錄到數(shù)據(jù)庫(kù)中那樣,我同樣也可以通過(guò)從DataContext的產(chǎn)品集合中移除一個(gè)Product對(duì)象來(lái)完成對(duì)數(shù)據(jù)庫(kù)中記錄的刪除:
?
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查詢來(lái)檢索出一個(gè)不再出售的,訂單數(shù)量為0的產(chǎn)品結(jié)果集,然后將它傳到DataContext的Products集合的RemoveAll()方法中。當(dāng)我們調(diào)用 SubmitChanges()訪求時(shí),所有的這些記錄將會(huì)從數(shù)據(jù)庫(kù)中刪除。
?
Updates across Relationships
通過(guò)關(guān)系進(jìn)行更新
?
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,特別靈活的是它們?cè)试S我們非常方便地通過(guò)我們的數(shù)據(jù)模型來(lái)對(duì)交叉的表間關(guān)系進(jìn)行建模。例如,我可以將每個(gè)Product放到一個(gè)Category中,每條Order可以包含OrderDetails,將每個(gè)OrderDetail的數(shù)據(jù)項(xiàng)跟產(chǎn)品關(guān)聯(lián)起來(lái),每個(gè)有一套訂單。在本系列的第二部分(Part 2)我講解了如何組織并生成這些關(guān)系。
?
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使得我在查詢和更新我的數(shù)據(jù)時(shí)均可以使用這些關(guān)系。例如,我可以寫(xiě)如下的代碼來(lái)生成一條新產(chǎn)品記錄,并將它與在數(shù)據(jù)庫(kù)中已經(jīng)存在的"Beverages"類(lèi)別關(guān)聯(lián)起來(lái):
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()".
注意上面我如何將一個(gè)Product對(duì)象添加到類(lèi)別的Products集合中。這表明了在兩個(gè)對(duì)象之間存在著關(guān)系,并且使得在調(diào)用SubmitChanges()方法時(shí)LINQ to SQL自動(dòng)地維護(hù)外鍵/主鍵關(guān)系。
?
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.
另外一個(gè)關(guān)于LINQ to SQL如何幫助我們管理表間交叉的關(guān)系并且使得我們的代碼更清潔的例子,讓我們看一下下面的一個(gè)為已經(jīng)存在的客戶生成一條訂單的事例。在設(shè)置了請(qǐng)求的時(shí)間和訂單的運(yùn)費(fèi)之后,我生成了兩個(gè)指向客戶訂下的產(chǎn)品的Order對(duì)象。然后將這個(gè)訂單和客戶關(guān)聯(lián)起來(lái),并且將所有的這些變更更新至數(shù)據(jù)庫(kù)。
?
As you can see, the programming model for performing all of this work is extremely clean and object oriented.?
正如你看到的,實(shí)現(xiàn)所有這些工作的編程模型特別的簡(jiǎn)單,并且是面向?qū)ο蟮摹?/span>
?
Transactions
?
事務(wù)
?
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.
?
事務(wù)是數(shù)據(jù)庫(kù)(或者其他的資源管理器)提供的一種服務(wù),該服務(wù)能保證一系列單獨(dú)的行為自動(dòng)的觸發(fā)――也就是要么它們?nèi)砍晒?#xff0c;要么就不成功,如果不成功的話,它們將會(huì)在允許做其他事情之前自動(dòng)地回滾。
?
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.
?
當(dāng)你調(diào)用DataContext的SubmictChanges()方法時(shí),更新部分總是會(huì)被包裝在一個(gè)事務(wù)中。這意味著如果你執(zhí)行了多步變更的話,你的數(shù)據(jù)庫(kù)永遠(yuǎn)不會(huì)處于不一致的情況――要么將你所有對(duì)DataContext做的變化保存至數(shù)據(jù)庫(kù),要么全不保存。
?
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.
?
如果沒(méi)有已經(jīng)排除的事務(wù),LINQ to SQL DataContext將會(huì)在調(diào)用SubmitChanges()方法時(shí)自動(dòng)地開(kāi)啟一個(gè)事務(wù)來(lái)進(jìn)行更新。另外,LINQ to SQL也允許你顯示地聲明并使用你自己的事務(wù)處理對(duì)象(在.Net2.0中介紹的一個(gè)特性)。這使得將LINQ to SQL代碼和現(xiàn)有的數(shù)據(jù)訪問(wèn)代碼集成變得更加容易。也意味著你可以將一個(gè)非數(shù)據(jù)庫(kù)資源添加到數(shù)據(jù)庫(kù)中――例如,你可以發(fā)送一條MSMQ消息,更新文件系統(tǒng)(用新的事務(wù)文件系統(tǒng)支持)等――并且將所有的這些工作放到同你用LINQ to SQL更新你數(shù)據(jù)庫(kù)的一個(gè)事務(wù)中。
Validation and Business Logic
驗(yàn)證和業(yè)務(wù)邏輯
?
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.?
開(kāi)發(fā)者在跟數(shù)據(jù)打交道時(shí)需要考慮的一個(gè)重要的事情就是如何將驗(yàn)證和業(yè)務(wù)邏輯結(jié)合起來(lái)。幸運(yùn)的是,LINQ to SQL支持開(kāi)發(fā)者清晰地將它們集成在數(shù)據(jù)模型中的各種各樣的方法。
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使得你添加一次這些驗(yàn)證邏輯――然后你就可以不用管你生成的數(shù)據(jù)模型如何被使用,也不用管在何處被使用。這避免了你在我處來(lái)重復(fù)你的驗(yàn)證規(guī)則,而且使得數(shù)據(jù)模型更具有可維護(hù)性和簡(jiǎn)潔性。
?
Schema Validation Support
架構(gòu)驗(yàn)證的支持
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.
當(dāng)使用VS2008中的LINQ to SQL設(shè)計(jì)器來(lái)定義數(shù)據(jù)模型為時(shí),它們會(huì)被默認(rèn)地加上從數(shù)據(jù)表中反映出來(lái)的驗(yàn)證規(guī)則。
?
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.
數(shù)據(jù)模型類(lèi)中的屬性的數(shù)據(jù)類(lèi)型要和數(shù)據(jù)庫(kù)中的數(shù)據(jù)項(xiàng)的數(shù)據(jù)類(lèi)型相一致。這意味著如果你試圖將一個(gè)boolean類(lèi)型賦值給一個(gè)decimal類(lèi)型的值,或者錯(cuò)誤的隱示地轉(zhuǎn)換一個(gè)數(shù)據(jù)類(lèi)型時(shí),你就會(huì)得到一個(gè)編譯錯(cuò)誤。
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.
如果數(shù)據(jù)庫(kù)中的一列被標(biāo)志為可空,那么數(shù)據(jù)模型類(lèi)相應(yīng)的屬性將是一個(gè)可空的類(lèi)型。如果你試圖對(duì)沒(méi)有被標(biāo)為可空的列賦空值,將會(huì)自動(dòng)拋出異常。 LINQ to SQL 將同樣確保標(biāo)識(shí)/唯一列被正確的賦值。
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.
如果你樂(lè)意的話,你可以使用LINQ to SQL 設(shè)計(jì)器覆蓋默認(rèn)的框架驗(yàn)證設(shè)置。但是在默認(rèn)情況下,這是自動(dòng)的并不需要額外的步驟來(lái)啟用它。LINQ to SQL 也會(huì)為你自動(dòng)管理SQL語(yǔ)句-所以在使用時(shí)你不必?fù)?dān)心SQL注入。
?
Custom Property Validation Support
自定義屬性驗(yàn)證支持
Schema driven datatype validation is useful as a first step, but usually?isn't enough for real-world scenarios.?
數(shù)據(jù)庫(kù)框架驗(yàn)證作為第一步非常有用,但是在實(shí)際的場(chǎng)景中并不足夠。
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:?
例如考慮這一場(chǎng)景,"Customer"類(lèi)有一個(gè)"phone"的屬性,被定義為NVarchar類(lèi)型,開(kāi)發(fā)者編寫(xiě)如下代碼,用一個(gè)合法的電話號(hào)碼來(lái)對(duì)它進(jìn)行更新:
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語(yǔ)句上來(lái)說(shuō),如下代碼依然是合法的(因?yàn)樗廊皇且粋€(gè)字符串,雖然不是一個(gè)電話號(hào)碼)
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:
為避免錯(cuò)誤的號(hào)碼插入到數(shù)據(jù)庫(kù)中,我們可以向Customer數(shù)據(jù)類(lèi)型類(lèi)中加入自定義的屬性驗(yàn)證規(guī)則。用這個(gè)特性來(lái)添加一條對(duì)電話號(hào)碼的驗(yàn)證規(guī)則確實(shí)非常簡(jiǎn)單。我們所需要做的是在項(xiàng)目中加一個(gè)新的部分類(lèi)來(lái)定義以下方法。:
?
The code above takes advantage of two characteristics of LINQ to SQL:
以上代碼利用了LINQ to SQL 兩個(gè)特性:
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 設(shè)計(jì)器生成的類(lèi)都被聲明為"局部"類(lèi) -這意味著開(kāi)發(fā)者可以向這些總局類(lèi)中很方便的增加方法,屬性,及事件。因此驗(yàn)證規(guī)則和用戶自定義的輔助方法可以很方便的加入數(shù)據(jù)模型類(lèi)和DataContext類(lèi)中。不需要設(shè)置或者代碼綁定。
?
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 揭示了數(shù)據(jù)模型類(lèi)及DataContext類(lèi)中很多用戶可擴(kuò)展的地方,在這些地方可以添加驗(yàn)證邏輯??蓴U(kuò)展的地方利用了一個(gè)新的語(yǔ)言特性,稱之為“部分方法”,這是VS2008Beta2 VB和C#引入的。Wes Dyer 在他的日志中對(duì)“部分方法”是如何工作的有很好的解釋(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.
在以上驗(yàn)證的示例中,我使用 OnPhoneChanging 部分方法,此方法將在程序設(shè)置“Customer”對(duì)象的“Phone”屬性時(shí)執(zhí)行。 如果我想的話我可以使用這個(gè)方法來(lái)驗(yàn)證輸入—(在此使用正則表達(dá)式)如果一切正確,將從此方法返回而且LINQ to SQL 將認(rèn)為該值合法。如果有什么錯(cuò)誤發(fā)生,在驗(yàn)證方法中拋出一個(gè)異常-這將阻止賦值。
Custom?Entity Object Validation Support
自定義實(shí)體對(duì)象驗(yàn)證支持
?
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.?
以上場(chǎng)景中的屬性級(jí)驗(yàn)證對(duì)驗(yàn)證數(shù)據(jù)模型類(lèi)的彼此獨(dú)立的屬性非常有用。有時(shí),你需要驗(yàn)證互相作用的多個(gè)屬性的值。
Consider for example a scenario with an Order object where you set both the "OrderDate" and the "RequiredDate" properties:
例如,設(shè)置訂單對(duì)象的 "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.?
上面代碼對(duì)于SQL數(shù)據(jù)庫(kù)來(lái)說(shuō)是合法的- 盡管將傳遞的時(shí)間設(shè)置為訂單時(shí)間的昨天是沒(méi)有任何意義的。
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 版本中,通過(guò)增加自定義實(shí)體級(jí)驗(yàn)證規(guī)則可以防止此類(lèi)錯(cuò)誤的發(fā)生。我們可以給“Order”實(shí)體增加一個(gè)部分類(lèi)并且實(shí)現(xiàn)OnValidate()的部分方法, 此方法將在實(shí)體值被保存在數(shù)據(jù)庫(kù)中之前調(diào)用。在此驗(yàn)證方法中我們可以訪問(wèn)和驗(yàn)證數(shù)據(jù)模型類(lèi)所有的屬性。
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.
在驗(yàn)證方法中可以檢查實(shí)體的屬性值(甚至只讀訪問(wèn)其關(guān)聯(lián)的對(duì)象),如果值不合法的話將拋出異常。任何拋出的異常將中止保存到數(shù)據(jù)庫(kù),并且回滾同一事務(wù)中其他的改動(dòng)。
Custom?Entity Insert/Update/Delete Method Validation
自定義實(shí)體插入/更新/刪除方法驗(yàn)證
?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.
? 經(jīng)常你需要的驗(yàn)證邏輯不單單是在獨(dú)立的插入/更新/刪除操作中。LINQ to SQL Beta2允許你將“局部方法”添加到DataContext類(lèi)中來(lái)為你的添加更新和刪除邏輯添加自定義的驗(yàn)證。這些方法在調(diào)用SubmitChanges()時(shí)將會(huì)被自動(dòng)調(diào)用。
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):
在這些方法中,你可以加入適當(dāng)?shù)尿?yàn)證邏輯。 - 如果驗(yàn)證邏輯通過(guò),它將通知 LINQ to SQL保存相關(guān)的改動(dòng)到數(shù)據(jù)庫(kù)。 (通過(guò)調(diào)用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:
一個(gè)比較好的地方是,以上方法在數(shù)據(jù)對(duì)象創(chuàng)建/更新/刪除時(shí)自動(dòng)匹配執(zhí)行。例如,如下示例, 我們創(chuàng)建一個(gè)新的定單關(guān)聯(lián)到一個(gè)存在的客戶。
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.?
在我們調(diào)用Northwind.SubmitChanges() 時(shí),, LINQ to SQL 將決定保存新的定單對(duì)象, "InsertOrder"部分方法將被自動(dòng)調(diào)用。
Advanced: Looking at the Entire Change List for the Transaction
高級(jí):事務(wù)中全部的發(fā)動(dòng)列表
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.?
經(jīng)常你需要的驗(yàn)證邏輯不單單是在獨(dú)立的插入/更新/刪除操作中。反而,你需要檢查在同一事務(wù)中發(fā)生的所有改動(dòng)。
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開(kāi)始,你可以通過(guò)調(diào)用DataContext.GetChangeList() 訪問(wèn)所有的改變列表。此方法返回一個(gè)ChangeList 對(duì)象,該對(duì)象包含了增加,刪除及修改的集合。
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:
在更高級(jí)的場(chǎng)景中,你可以繼承DataContext類(lèi),重寫(xiě)SubmitChange()方法。在保存到數(shù)據(jù)庫(kù)之前,通過(guò)獲取更新操作的ChangeList()進(jìn)行自定義的驗(yàn)證
?
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.
以上是一個(gè)高級(jí)的場(chǎng)景--但是最好你要在需要的時(shí)候 ,你可以實(shí)現(xiàn)并能利用它。
Handling Simultaneous Changes with Optimistic Concurrency
樂(lè)觀并發(fā)控制
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.?
開(kāi)發(fā)者需要關(guān)心的一點(diǎn)是,在多用戶的數(shù)據(jù)庫(kù)系統(tǒng)中,如何處理同一數(shù)據(jù)同時(shí)更新。例如,假定兩個(gè)用在以各應(yīng)用中獲取一個(gè)產(chǎn)品對(duì)象,其中一個(gè)用戶設(shè)置RecorderLevel為0,而另外一個(gè)用戶設(shè)置為1。如果兩個(gè)用戶試圖將此產(chǎn)品保存到數(shù)據(jù)庫(kù),開(kāi)發(fā)者需要決定如何處理這個(gè)改動(dòng)的沖突。
?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.?
一種解決方法是 "最后寫(xiě)入者贏" - 這意味著第一位用戶沒(méi)有的到提示的情況下,其提交的值將被丟掉。通常這被認(rèn)為是一個(gè)不好(不正確)的應(yīng)用經(jīng)驗(yàn)。
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.?
另外一個(gè)方法是 LINQ to SQL 支持樂(lè)觀并發(fā)模型。 -? 在保存新值之前,LINQ to SQL 將自動(dòng)探測(cè)原值已被其他人修改.? LINQ to SQL 然后可以提供一個(gè)改變值得沖突列表,這樣開(kāi)發(fā)者或者協(xié)調(diào)數(shù)值之間的差距,或者在UI中提示用戶要如何處理。
I'll cover how to use optimistic concurrency with LINQ to SQL in a future blog post.
在以后的帖子中我將講解如何用LINQ to SQL處理樂(lè)觀并發(fā)沖突。
Using SPROCs or Custom SQL?Logic for Insert/Update/Delete Scenarios
用存儲(chǔ)過(guò)程或者自定義的SQL語(yǔ)句來(lái)插入/更新/刪除記錄的情景
?
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?"?
?
那些過(guò)去用SQL語(yǔ)句寫(xiě)自定義的存儲(chǔ)過(guò)程(尤其DBA們)在第一次見(jiàn)到LINQ to SQL時(shí)經(jīng)常問(wèn)的一個(gè)問(wèn)題是—"可是我如何完全地控制它執(zhí)行的SQL語(yǔ)句?"
?
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.?
?
有一個(gè)好的消息,就是LINQ to SQL有一個(gè)非常之靈活的模型,該模型允許開(kāi)發(fā)者們重寫(xiě)LINQ to SQL動(dòng)態(tài)生成的SQL語(yǔ)句,用他們自定義的插入/更新/刪除的存儲(chǔ)過(guò)程來(lái)替代那些生成的SQL語(yǔ)句.
?
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.
?
真正好的一點(diǎn)是你可以通過(guò)定義你的數(shù)據(jù)模型來(lái)讓LINQ to SQL自動(dòng)的處理插入/更新/刪除的SQL邏輯。你可以為更新定義一個(gè)你自己的存儲(chǔ)過(guò)程或者SQL語(yǔ)句-這樣在以后更新應(yīng)用程序時(shí)你可以既不必去更改應(yīng)用了你的數(shù)據(jù)模型的應(yīng)用程序的邏輯,又不必去更改任何的驗(yàn)證或者業(yè)務(wù)邏輯(所有的這些使用原有的即可)。這在你如何構(gòu)建應(yīng)用程序上提供了很大的靈活性。
?
I'll cover how to customize your data models to use SPROCs or custom SQL in a future blog post.
在接下來(lái)的一篇帖子中我將會(huì)講解一下如何自定義你的數(shù)據(jù)模型來(lái)使用存儲(chǔ)過(guò)程或者自定義的SQL語(yǔ)句。
?
?
Summary
?
總結(jié)
?
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方便地更新你的數(shù)據(jù)庫(kù)的,如何清晰地將你的驗(yàn)證及業(yè)務(wù)邏輯和你的數(shù)據(jù)模型結(jié)合起來(lái)的一個(gè)好的概述。我想你會(huì)發(fā)現(xiàn),在和數(shù)據(jù)打交道時(shí),LINQ to SQL會(huì)極大地提高你的生成力,并且能夠讓你寫(xiě)出非常整潔的面向?qū)ο蟮臄?shù)據(jù)訪問(wèn)的代碼。
?
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的數(shù)據(jù)模型的情況下在ASP.NET中建立一個(gè)數(shù)據(jù)的UI是多么地方便!我會(huì)更近一步地講術(shù)一下LINQ to SQL的編程思想,包括優(yōu)化并發(fā)沖突,延遲和提前加載,表映射的繼承,自定義的存儲(chǔ)過(guò)程的使用等。
Hope this helps,
希望這些能對(duì)你有所幫助
Scott
轉(zhuǎn)載于:https://www.cnblogs.com/hanxianlong/archive/2007/11/19/962696.html
總結(jié)
以上是生活随笔為你收集整理的ScottGu之博客翻译-LINQ to SQL第四部分,更新数据库 LINQ to SQL (Part 4 - Updating our Database)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: WebSphere Applicatio
- 下一篇: 连接oracle10g数据库免安装ora