代码之家  ›  专栏  ›  技术社区  ›  Kelsey

如何在linq to sql中插入或更新where子句?

  •  3
  • Kelsey  · 技术社区  · 14 年前

    我正在尝试将以下存储过程转换为linqtosql调用(这是sql的简化版本):

    INSERT INTO [MyTable]
        ([Name], [Value])
    SELECT
        @name, @value
    WHERE
       NOT EXISTS(SELECT [Value] FROM [MyTable] WHERE [Value] = @value)
    

    数据库对要检查的字段没有限制,因此在这种特定情况下,需要手动进行检查。此外,还有许多项不断被插入,所以我需要确保当这个特定的插入发生时,不会重复值字段。我的第一个预感是:

    using (TransactionScope scope = new TransactionScope())
    {
        if (Context.MyTables.SingleOrDefault(t => t.Value == in.Value) != null)
        {
            MyLinqModels.MyTable t = new MyLinqModels.MyTable()
            {
               Name = in.Name,
               Value = in.Value
            };
    
            // Do some stuff in the transaction
    
            scope.Complete();
        }
    }
    

    这是我第一次真正遇到这种情况,所以我想确保我的做法是正确的。这似乎是正确的还是有人能建议一个更好的方法来解决这个问题而不需要两个单独的电话?

    编辑: 我遇到了一个类似的问题,有一个更新:

    UPDATE [AnotherTable]
    SET [Code] = @code
    WHERE [ID] = @id AND [Code] IS NULL
    

    我如何与linqtosql进行相同的检查?我假设我需要执行get,然后设置所有值并提交,但是如果有人在执行更新时将[代码]更新为null以外的其他值怎么办?

    与插入相同的问题…

    3 回复  |  直到 14 年前
        1
  •  1
  •   Aaronaught    14 年前

    把这个包在 TransactionScope 如果数据库中没有唯一约束,则实际上不会防止冲突。它只保证原子性 交易。

    在一个大容量的场景中,完全有可能并且很可能有两个同时的事务通过第一个事务 null 在开始更新之前检查(这只是一个阅读)。在数据库本身中强制实施唯一性约束非常重要—如果在这里不能做到这一点,那么您的工作就要为您完成了。

    老实说,根据您的要求,我建议您改为使用存储过程。linq to sql是一个很好的工具,但它做不到 一切 SQL可以;这似乎是需要比L2实际提供的更多控制的情况之一。

        2
  •  1
  •   Marc Gravell    14 年前

    如果这是一个 想不到的 大小写(即表示错误),a UNIQUE 约束应该足够了。

    没有 直接的 通过linq to sql来实现,所以 TransactionScope (或) SqlTransaction 在传入的连接上)是 可行的机制。另一 可以 是一个代替触发器,或一个存储过程来执行 INSERT .

    你所拥有的可能是最简单的;看看它是否足够快(它有一个额外的往返)并坚持下去?

        3
  •  1
  •   Daniel Schaffer    14 年前

    我不相信linq-to-sql可以做到这一点,但是更好的选择是使用 Any() 而不是 SingleOrDefault() :

    using (TransactionScope scope = new TransactionScope())
    {
        if (!Context.MyTables.Any(t => t.Value == in.Value))
        {
            MyLinqModels.MyTable t = new MyLinqModels.MyTable()
            {
               Name = in.Name,
               Value = in.Value
            };
    
            // Do some stuff in the transaction
    
            scope.Complete();
        }
    }
    

    我相信 任意() 使用 EXISTS SQL中的关键字,它选择一个布尔值,而不是该行中所有列的全部内容。

    Aaron关于使用存储过程的建议可能会更为直接——而且您还可以将其连接到数据上下文。