2012-06-25 80 views
1

我有以下用于更新帐户表与LINQ to SQL的代码。 AccountNumber是主键列。唯一需要更新的值是AccountType;但持续时间也会更新为零(int的默认值)。我们如何避免这种不必要的覆盖?LINQ to SQL更新中的问题(C#变量的)问题

注:我使用附加方法

注:我理解这种现象的原因。 “DataContext无法区分赋值为零的字段和只是未赋值的字段。”我正在寻找解决方案来克服这一点。

[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Duration", DbType="Int NOT NULL" 
public int Duration 

表数据

enter image description here

表结构:

CREATE TABLE [dbo].[Account](
[AccountNumber] [int] NOT NULL, 
[AccountType] [nchar](10) NOT NULL, 
[Duration] [int] NOT NULL, 
[DepositedAmount] [int] NULL, 
CONSTRAINT [PK_Account] PRIMARY KEY CLUSTERED 
(
[AccountNumber] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

CODE

public void UpdateAccount() 
    { 
     RepositoryLayer.Account acc1 = new RepositoryLayer.Account(); 
     acc1.AccountNumber = 4; 
     acc1.AccountType = "Verify"; 

     accountRepository.UpdateChangesByAttachAndRefresh(acc1); 
     accountRepository.SubmitChanges(); 

    } 


    public virtual void UpdateChangesByAttachAndRefresh(T entity) 
    { 

     //Can GetOriginalEntityState cause any bug? Is it unnecessary?   
     if (GetTable().GetOriginalEntityState(entity) == null) 
     { 
      //If it is not already attached 

      Context.GetTable<T>().Attach(entity); 
      Context.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, entity); 


     } 

    } 

生成的SQL

UPDATE [dbo].[Account] 
SET [AccountType] = @p3, [Duration] = @p4 
WHERE ([AccountNumber] = @p0) 
AND ([AccountType] = @p1) 
AND ([Duration] = @p2) 
AND ([DepositedAmount] IS NULL) 

-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [4] 
-- @p1: Input NChar (Size = 10; Prec = 0; Scale = 0) [TEST  ] 
-- @p2: Input Int (Size = -1; Prec = 0; Scale = 0) [10] 
-- @p3: Input NChar (Size = 10; Prec = 0; Scale = 0) [Verify] 
-- @p4: Input Int (Size = -1; Prec = 0; Scale = 0) [0] 

-- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1 

READING:

  1. Can LINQ-to-SQL omit unspecified columns on insert so a database default value is used?

  2. How can I bind an Enum to a DbType of bit or int?

  3. Linq to SQL: Why am I getting IDENTITY_INSERT errors?

  4. LINQ to SQL: Updating without Refresh when “UpdateCheck = Never”

回答

1

我通过以下的LINQ to SQL: Updating without Refresh when “UpdateCheck = Never”

UpdateCheck的答案修改更新方法设置为从不为持续时间列

public void UpdateAccount() 
    { 
     //Used value from previous select 
     DateTime previousDateTime = new DateTime(2012, 6, 26, 11, 14, 15, 327); 
     int prevDuration = 0; 

     RepositoryLayer.Account accEntity = new RepositoryLayer.Account(); 
     accEntity.AccountNumber = 1; //Primary Key 
     accEntity.ModifiedTime = previousDateTime; //Concurrency column 
     //accEntity.Duration = prevDuration; 

     accountRepository.UpdateChangesByAttach(accEntity); 

     //Values to be modified after Attach 
     accEntity.AccountType = "WIN-WIN"; 
     accEntity.ModifiedTime = DateTime.Now; 

     try 
     { 
      accountRepository.SubmitChanges(); 
     } 
     catch(System.Data.Linq.ChangeConflictException e) 
     { 
      throw new Exception(e.Message); 
     } 

    } 


    public virtual void UpdateChangesByAttach(T entity) 
    { 

     if (Context.GetTable<T>().GetOriginalEntityState(entity) == null) 
     { 
      //If it is not already attached 
      Context.GetTable<T>().Attach(entity); 
     } 

    } 
解决了这个问题

生成的SQL

UPDATE [dbo].[Account] 
SET [AccountType] = @p2, [ModifiedTime] = @p3 
WHERE ([AccountNumber] = @p0) 
     AND ([ModifiedTime] = @p1) 

-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [1] 
-- @p1: Input DateTime (Size = -1; Prec = 0; Scale = 0) [6/26/2012 11:14:15 AM] 
-- @p2: Input NChar (Size = 10; Prec = 0; Scale = 0) [WIN-WIN] 
-- @p3: Input DateTime (Size = -1; Prec = 0; Scale = 0) [6/26/2012 11:16:29 AM] 
4

这应该这样做:

int number = 4; 
var acc1 = new accountRepository.Accounts.Where(a => a.Number == number).FirstOrDefault(); 

if (acc1 == null) 
{ 
    // Not found by ID, create new 
    acc1 = new RepositoryLayer.Account(); 
    acc1.Number = number; 
    accountRepository.Accounts.AddObject(acc1); 
} 

acc1.AccountType = "Verify"; 

accountRepository.SubmitChanges(); 
+0

谢谢。当我们使用“附加”和刷新方法时,我们不能实现它吗? – Lijo

+0

@Lijo:Attach在过去只引起我的问​​题。请使用上述方法; p – leppie

+0

@leppie您能否列出这些问题或提供参考? – Lijo