[英]Spurious DuplicateKeyException from Linq-to-SQL SubmitChanges
[英]Querying Linq-to-SQL updated values [pre-SubmitChanges()]
我有一種情況,我想與已更新但尚未使用'SubmitChanges()提交回數據庫的Linq-to-Sql托管數據(VS2008 / .NET Framework 3.5 / Sql Server 2005 Express)進行交互。 '。
我在下面給出了一個簡單的測試用例,其中我更改了一個簡單的“塊”對象的color屬性。 我枚舉了該表(塊9和10最初的Color值為空),更改了值,並枚舉了結果,一切似乎都很好。 但是,當我嘗試查詢(.Count)“塊”對象時,有些奇怪(或我的理解上的空白)在下面的兩個粗體輸出語句中突出顯示。
語句LinqtoSqlDBDataContext.Blocks.Count(Block => Block.Color == null)導致值'2'...這很奇怪,因為前面的枚舉表明所有Block都分配了顏色。 該語句是否傳回數據庫(實際上“ 2”將是正確的值,因為尚未提交任何內容)? db跟蹤可以確認SELECT語句。
第二條語句LinqtoSqlDBDataContext.Blocks.ToList()。Count(Block => Block.Color == null)返回正確的值'0',但是我不確定'ToList()'為什么會影響結果,所以。 您將注意到,該語句還生成了完全不同的SQL語句(沒有要引導的WHERE子句)。
如果未注釋SubmitChanges()行,則LinqtoSqlDBDataContext.Blocks.Count(Block => Block.Color == null)會返回正確的值。 但是,我無法始終預測更改的數量,因此我想盡可能地輕描淡寫地返回更新數據庫的次數。
所以我想我的問題是...根據我在這里看到的內容,與預先提交的數據進行交互是否安全/有效/推薦? 我已經進行了廣泛搜索,但沒有找到關於此場景的太多信息(如果有的話)。 顯然有什么東西讓我迷失了嗎? 任何想法都深表感謝。
摘要 :預先提交的Linq-to-Sql數據的枚舉似乎返回與查詢預先提交的Linq-to-Sql數據不同的結果。
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[Block]( [ID] [int] IDENTITY(1,1) NOT NULL, [Color] [varchar](50) NULL, CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED ( [ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO SET ANSI_PADDING OFF
using System; using System.Collections.Generic;co using System.Linq; using System.Text; using System.Data.Linq; namespace LinqToSql1 { class Program { static void Main(string[] args) { LinqtoSqlDBDataContext LinqtoSqlDBDataContext = new LinqtoSqlDBDataContext(); LinqtoSqlDBDataContext.Log = Console.Out; Console.WriteLine("Enumerating Blocks\n=================="); foreach(Block Block in LinqtoSqlDBDataContext.Blocks) { Console.WriteLine("Block {0} Color is '{1}'", Block.ID, Block.Color); } Console.WriteLine(); Console.WriteLine("Updating Blocks\n==============="); foreach(Block Block in LinqtoSqlDBDataContext.Blocks.Where(b => b.Color == null)) { Console.WriteLine("Block {0} Color was '{1}'", Block.ID, Block.Color); Block.Color = "Gray"; Console.WriteLine("Block {0} Color is '{1}'", Block.ID, Block.Color); } Console.WriteLine(); Console.WriteLine("Enumerating Blocks\n=================="); foreach(Block Block in LinqtoSqlDBDataContext.Blocks) { Console.WriteLine("Block {0} Color is '{1}'", Block.ID, Block.Color); } Console.WriteLine(); // Console.WriteLine("Submitting Changes\n=================="); // LinqtoSqlDBDataContext.SubmitChanges(); Console.WriteLine("Counting Blocks\n==============="); Console.WriteLine("LinqtoSqlDBDataContext.Blocks.Count(Block => Block.Color == null) is {0}\n", LinqtoSqlDBDataContext.Blocks.Count(Block => Block.Color == null)); Console.WriteLine("LinqtoSqlDBDataContext.Blocks.ToList().Count(Block => Block.Color == null) is {0}\n", LinqtoSqlDBDataContext.Blocks.ToList().Count(Block => Block.Color == null)); LinqtoSqlDBDataContext.Dispose(); Console.WriteLine("Press [Enter] to continue"); Console.ReadLine(); } } }
Enumerating Blocks ================== SELECT [t0].[ID], [t0].[Color] FROM [dbo].[Block] AS [t0] -- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1 Block 1 Color is 'Red' Block 2 Color is 'Green' Block 3 Color is 'Yellow' Block 4 Color is 'Black' Block 5 Color is 'Orange' Block 6 Color is 'Purple' Block 7 Color is 'Blue' Block 8 Color is 'White' Block 9 Color is '' Block 10 Color is '' Updating Blocks =============== SELECT [t0].[ID], [t0].[Color] FROM [dbo].[Block] AS [t0] WHERE [t0].[Color] IS NULL -- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1 Block 9 Color was '' Block 9 Color is 'Gray' Block 10 Color was '' Block 10 Color is 'Gray' Enumerating Blocks ================== SELECT [t0].[ID], [t0].[Color] FROM [dbo].[Block] AS [t0] -- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1 Block 1 Color is 'Red' Block 2 Color is 'Green' Block 3 Color is 'Yellow' Block 4 Color is 'Black' Block 5 Color is 'Orange' Block 6 Color is 'Purple' Block 7 Color is 'Blue' Block 8 Color is 'White' Block 9 Color is 'Gray' Block 10 Color is 'Gray' Counting Blocks =============== SELECT COUNT(*) AS [value] FROM [dbo].[Block] AS [t0] WHERE [t0].[Color] IS NULL -- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1 LinqtoSqlDBDataContext.Blocks.Count(Block => Block.Color == null) is 2 SELECT [t0].[ID], [t0].[Color] FROM [dbo].[Block] AS [t0] -- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1 LinqtoSqlDBDataContext.Blocks.ToList().Count(Block => Block.Color == null) is 0 Press [Enter] to continue
如果要保留這些值,則可能必須先序列化結果,然后再進行修改。 例如
Console.WriteLine("Updating Blocks\n===============");
var blocksToUpdate = LinqtoSqlDBDataContext.Blocks.Where(b => b.Color == null).ToArray();
foreach( var block in blocksToUpdate )
{
// do something...
}
這樣,對象將保留其狀態,盡管這可能會導致問題/需要您以不同的方式進行提交更改。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.