同时更改两行

时间:2010-07-08 02:06:25

标签: sql linq-to-sql transactions

上下文:ASP.NET MVC 2.0,Linq-to-Sql,.Net 3.5,IIS7,MS SQL 2008

我正在开发一个游戏迷网站。

我有一张表格如下:

ToonId int (primary key)
RealmId (FK into Realms table)
OwnerId int (FK into Users table)
ToonName nvarchar(50)
IsMain bit

单个用户可能在多个领域(也称为服务器)上拥有多个toons,但是每个领域必须将一个toon标记为每个用户的主要(仅适用于至少有一个香椿的领域)。

假设我有两个卡通(在一个领域): Foo(标记为主要)
和 酒吧(不是主要的)

我想改变我的主要内容,为此我做了类似的事情:     Foo.IsMain = false     Bar.IsMain = true

我正在使用Linq-to-SQL。

问题:当我有一个或多个主要卡通时,如何在不进入状态的情况下进行所述转换。

注意:我有一个物化视图(由IsMain = 1过滤),它定义了一个复合键(OwnerId,RealmId),因此当我执行main-toon过渡时,我从该物化视图中获得“唯一键冲突”异常。

已经尝试使用事务,但我仍然在'db.SubmitChanges()'上获得异常。

选项2:我怀疑我在数据库设计中存在缺陷(这个漏洞的名称是什么?)。我应该创建映射表吗?

OwnerId, RealmId -> ToonId

1 个答案:

答案 0 :(得分:1)

问题1

您需要使用交易。

 DBDataContext db = new DBDataContext();
 using (TransactionScope ts = new TransactionScope())
 {
     try
     {
         Toon toon1 = db.Toons.First(p => p.ToonId == 4);
         Toon toon2 = db.Toons.First(p => p.ToonId == 5);
         toon1.IsMain = false;
         toon2.IsMain = true;
         db.SubmitChanges();
         ts.Complete();
     }
     catch (Exception e)
     {
        Console.WriteLine(e.Message);
     }
}

问题2

你需要多考虑一下你的设计。

第1步

这是一个拥有主Toon的玩家所以我会在你的用户桌上放置一个MainToonId并从你的Toon表中删除你的IsMain。

在此之后,您的表将是Users(Existing Stuff,MainToonId),Realms(Existing Stuff),Toons(ToonId,RealmId,OwnerId,ToonName)

第2步

正如您所建议的,您可以将Realm / Owner / Toon链接移动到其自己的表(甚至ToonOwner和ToonRealm表)。链接信息相关,但它不是Toon的识别部分。这个“缺陷”的解决方案是规范化,需要它的数据库被描述为“需要规范化”。但是,在这种情况下,此步骤完全可选,并且可能会过度规范化以满足您的需求。

如果您确实选择了一个比赛表,那么新表将会有3个值组合的PK(如果您是天生的键控器),否则标准PK和3个值上的UNIQUE(如果您不是自然的话)键控器)。你应该在ToonId上有一个独特的,因为每个Toon可能只属于一个领域或所有者。