惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
I
InfoQ
博客园 - 三生石上(FineUI控件)
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 【当耐特】
T
The Blog of Author Tim Ferriss
N
Netflix TechBlog - Medium
GbyAI
GbyAI
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
B
Blog RSS Feed
Blog — PlanetScale
Blog — PlanetScale
酷 壳 – CoolShell
酷 壳 – CoolShell
WordPress大学
WordPress大学
L
LINUX DO - 热门话题
Security Latest
Security Latest
月光博客
月光博客
U
Unit 42
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threat Research - Cisco Blogs
The GitHub Blog
The GitHub Blog
Simon Willison's Weblog
Simon Willison's Weblog
Help Net Security
Help Net Security
人人都是产品经理
人人都是产品经理
Engineering at Meta
Engineering at Meta
罗磊的独立博客
Attack and Defense Labs
Attack and Defense Labs
MongoDB | Blog
MongoDB | Blog
Microsoft Azure Blog
Microsoft Azure Blog
S
Securelist
P
Proofpoint News Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
A
About on SuperTechFans
PCI Perspectives
PCI Perspectives
S
Security Affairs
Schneier on Security
Schneier on Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
L
LangChain Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
H
Hacker News: Front Page
C
Cyber Attacks, Cyber Crime and Cyber Security
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Security Archives - TechRepublic
Security Archives - TechRepublic
P
Privacy & Cybersecurity Law Blog
W
WeLiveSecurity
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
K
Kaspersky official blog
Google Online Security Blog
Google Online Security Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
V
Vulnerabilities – Threatpost
Recorded Future
Recorded Future

博客园 - Animax!

The Tao of Programming Light weight Framework (AnyBase) -- 通信模块说明 关于WinIO.DLL的键盘输入模拟 Light weight Framework (AnyBase) -- Core 模块说明 开源项目 Light weight Framework (AnyBase) 发布 DB4o的缓存机制 Winfrom界面异步操作的一个解决方法 db4o 研究--性能测试 Asp.net动态数据(Dynamic Data) 笔记一 MVC — 笔记 WF笔记 – Workflow概念 WCF Demo – Http、TCP Host - Animax! WCF笔记 - 绑定 WCF 笔记 正则表达式[转载整理] - Animax! - 博客园 LINQ 笔记 - LINQ to SQL 基本数据操作 - Animax! LINQ 笔记 - 语法与关键字 LINQ 笔记- Lambda Excel导入SQL - Animax! - 博客园
LINQ TO SQL 笔记 — 存储过程、并发与事务
Animax! · 2008-04-17 · via 博客园 - Animax!

2008-04-17 22:57  Animax!  阅读(1543)  评论()    收藏  举报

前期设定:

先定义有两个数据表:

CREATE TABLE [dbo].[Table_A](

         [AID] [bigint] IDENTITY(1,1) NOT NULL,

         [name] [text] COLLATE Chinese_PRC_CI_AS NULL,

         [name2] [text] COLLATE Chinese_PRC_CI_AS NULL,

         [name3] [text] COLLATE Chinese_PRC_CI_AS NULL,

 CONSTRAINT [PK_Table_A] PRIMARY KEY CLUSTERED

(

         [AID] ASC

)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]

) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

CREATE TABLE [dbo].[Table_B](

         [BID] [bigint] IDENTITY(1,1) NOT NULL,

         [AID] [bigint] NULL,

         [text] [text] COLLATE Chinese_PRC_CI_AS NULL,

         [text2] [text] COLLATE Chinese_PRC_CI_AS NULL,

 CONSTRAINT [PK_Table_B] PRIMARY KEY CLUSTERED

(

         [BID] ASC

)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]

) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

ALTER TABLE [dbo].[Table_B] WITH CHECK ADD CONSTRAINT [FK_Table_A_Table_B] FOREIGN KEY([AID])

REFERENCES [dbo].[Table_A] ([AID])

GO

ALTER TABLE [dbo].[Table_B] CHECK CONSTRAINT [FK_Table_A_Table_B]

三个存储过程:

ALTER PROCEDURE [dbo].[GetTableA_And_B] 单结果集返回

         @TableAID bigint

AS

BEGIN

         SET NOCOUNT ON;

SELECT                Table_B.BID, Table_B.text, Table_B.text2,

                            Table_A.AID, Table_A.name, Table_A.name3, Table_A.name2

FROM         Table_B INNER JOIN Table_A ON Table_B.AID = Table_A.AID

WHERE               Table_A.AID = @TableAID

END

ALTER PROCEDURE [dbo].[GetTableA_ID_by_TableB_ID] -–传入传出值

         @BID bigint,

         @AID bigint output

AS

BEGIN

         SET NOCOUNT ON;

         select @AID = AID from Table_B

         where BID = @BID

END

ALTER PROCEDURE [dbo].[GetTables] -–双结果集返回

         @TableA_ID        bigint

AS

BEGIN

 SET NOCOUNT ON;

         SELECT     AID, name, name2, name3

         FROM         Table_A

         where AID = @TableA_ID

         SELECT     BID, AID, text, text2

         FROM         Table_B

         where AID = @TableA_ID

END

并且设置工程添加了一个名为MyLINQDataLINQ TO SQL类,在这类中加入了需要的表和存储过程。

LINQ TO SQL调用存储过程:

有返回值的存储过程(GetTableA_ID_by_TableB_ID):

            MyLINQDataDataContext data = new MyLINQDataDataContext();

            long? TableAID = 0;

            data.GetTableA_ID_by_TableB_ID(3, ref TableAID);

            Console.WriteLine(string.Format("TableA.ID = {0}", TableAID));

返回单结果集的存储过程(GetTableA_And_B):

            MyLINQDataDataContext data = new MyLINQDataDataContext();

            var revalue = data.GetTableA_And_B(1);

            foreach (var val in revalue)

            {

                Console.WriteLine(string.Format(

                    "AID:{0}||BID:{1}||name:{2}||name1:{3}||name2:{4}||text:{5}||text2:{6}",

                    val.AID, val.BID, val.name, val.name2, val.name3, val.text, val.text2));

            }

返回多结果集的存储过程(GetTables):

使用返回多结果集的存储过程比较麻烦,在LINQ TO SQL类中只识别到一个(第一个)结果集,所以需要手动修改生成的DataContext类,

原本的GetTables方法:

        [Function(Name = "dbo.GetTables")]

        public ISingleResult<GetTablesResult> GetTables([Parameter(Name = "TableA_ID", DbType = "BigInt")] System.Nullable<long> tableA_ID)

        {

            IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), tableA_ID);

            return ((ISingleResult<GetTablesResult>)(result.ReturnValue));

        }

修改后的方法:

        [Function(Name = "dbo.GetTables")]

        [ResultType(typeof(Table_A))]         //这里是第一个结果集,返回的是Table_A的内容

        [ResultType(typeof(Table_B))] //这里是第二个结果集

        public IMultipleResults GetTables([Parameter(Name = "TableA_ID", DbType = "BigInt")] System.Nullable<long> tableA_ID)

        {

            IExecuteResult result = this.ExecuteMethodCall(this,((MethodInfo)(MethodInfo.GetCurrentMethod())), tableA_ID);

            return ((IMultipleResults)(result.ReturnValue));

        }

多结果集的调用方式

            MyLINQDataDataContext data = new MyLINQDataDataContext();

            var revalue = data.GetTables(1);

            var TableA = revalue.GetResult<Table_A>();

            var TableB = revalue.GetResult<Table_B>();

            foreach (var TA in TableA)

            {

                Console.WriteLine(string.Format(

                    "AID:{0}||name:{1}||name2:{2}||name3:{3}",

                    TA.AID, TA.name, TA.name2, TA.name3));

            }

            Console.WriteLine();

            foreach (var TB in TableB)

            {

                Console.WriteLine(string.Format(

                    "AID:{0}||BID:{1}||text:{2}||text2:{3}",

                    TB.AID, TB.BID, TB.text, TB.text2

                    ));

            }

LINQ TO SQL更新冲突:

需要 using System.Data.Linq;

更新冲突是指在赋值后和提交修改前数据库中设计修改的值发生了变化:

            MyLINQDataDataContext data = new MyLINQDataDataContext();

            var TableA =

                from Table in data.Table_A

                select Table;

            foreach (var value in TableA)

            {

                value.name = "updateName";

                value.name2 = "updateName2";

                value.name3 = "updaeName3";

            }

                      // 这时数据被改变了….

            data.SubmitChanges(System.Data.Linq.ConflictMode.FailOnFirstConflict);

这里要说明一下System.Data.Linq.ConflictMode这个枚举类型的值:

FailOnFirstConflict : 当发现数据库数据已经改变,对发生了更改的数据不进行更新(未发生更改的数据继续进行更新)。

ContinueOnConflict : 先对数据进行更改,然后提交冲突报告。

在使用ContinueOnConflict模式的数据更新中,可以使用ChangeConflictException 来捕获冲突异常。

当捕获到并发冲突异常之后,可以使用数据库实体(Context)的ContinueOnConflict来获取发生冲突的对象;并可以使用Resolve方法来解决数据冲突的问题。

Resolve方法可以接受3种解决方式(RefreshMode):

KeepCurrentValues使用数据库中的值覆盖当前值。(以现在的更新为准)

KeepChanges:使用从数据库检索的值替换原始值。(原来的更新有效,冲突字段以当前的更新为准)

OverwriteCurrentValues保留已更改的当前值,但将其他值更新为数据库值。(更新以数据库更新为准)

            try

            {

                data.SubmitChanges(System.Data.Linq.ConflictMode.ContinueOnConflict);

            }

            catch (ChangeConflictException) //捕获到冲突

            {

                foreach (ObjectChangeConflict OC in data.ChangeConflicts)

                {

                    OC.Resolve(RefreshMode.OverwriteCurrentValues);

                }

            }

LINQ TO SQL事务:

需要 using System.Data.Common;

            MyLINQDataDataContext data = new MyLINQDataDataContext();

            if (data.Connection != null) //打开连接

            {

                data.Connection.Open();

            }

            // BeginTransaction 可以传入事务的隔离类型。

            DbTransaction tran = data.Connection.BeginTransaction(); // 隔离类型为:Unspecified

            data.Transaction = tran;

            try

            {

                var TableA =

                    from Table in data.Table_A

                    select Table;

                foreach (var value in TableA)

                {

                    value.name = "test";

                    value.name2 = "test";

                    value.name3 = "test";

                }

                data.SubmitChanges(); //更新数据

                tran.Commit(); // 提交事务

            }

            catch

            {

                tran.Rollback();

            }

在事务CommitRollback 之前数据是被锁着的,锁的类型视乎于事务的隔离等级,在默认情况下是(Unspecified)。

隔离等级System.Data.IsolationLevel的枚举值:

Unspecified正在使用与指定隔离级别不同的隔离级别,但是无法确定该级别。

Chaos无法覆盖隔离级别更高的事务中的挂起的更改。

ReadUncommitted可以进行脏读,意思是说,不发布共享锁,也不接受独占锁。

ReadCommitted在正在读取数据时保持共享锁,以避免脏读,但是在事务结束之前可以更改数据,从而导致不可重复的读取或幻像数据。

RepeatableRead在查询中使用的所有数据上放置锁,以防止其他用户更新这些数据。防止不可重复的读取,但是仍可以有幻像行。

Serializable DataSet 上放置范围锁,以防止在事务完成之前由其他用户更新行或向数据集中插入行。

Snapshot通过在一个应用程序正在修改数据时存储另一个应用程序可以读取的相同数据版本来减少阻止。表示您无法从一个事务中看到在其他事务中进行的更改,即便重新查询也是如此。