关于.net:默认值(C#变量)LINQ to SQL Update中的问题

Default Values (of C# variables) Issue in LINQ to SQL Update

我有以下代码用于用linq to sql更新account表。AccountNumber是主键列。唯一需要更新的值是accounttype;但是持续时间也会更新为零(int的默认值)。我们如何避免这种不必要的覆盖?

注意:我使用的是附加方法

注意:我理解这种行为的原因。"DataContext无法区分赋值为零的字段和仅未赋值的字段。"。我正在寻找解决办法来克服这个问题。

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

表数据

enter image description here

表结构:

1
2
3
4
5
6
7
8
9
10
 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]

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

阅读:

  • LINQ to SQL能否在插入时省略未指定的列,以便使用数据库默认值?

  • 如何将枚举绑定到bit或int的dbtype?

  • Linq to SQL:为什么我会收到标识插入错误?

  • linq to sql:updatecheck=never时不刷新更新


  • 应该这样做:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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();


    我通过更改更新方法来解决这个问题,方法是按照linq to sql中的答案:当"updatecheck=never"时不刷新更新

    对于Duration列,UpdateCheck设置为Never

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
        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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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]