【问题标题】:Update multiple sequence numbers on unique index更新唯一索引上的多个序列号
【发布时间】:2016-09-30 15:32:39
【问题描述】:

类似于this question 我在两个字段上有一个唯一索引,将 ID 字段和序列号限制为唯一。现在我通过拖放更改序列号 - 之后这些数字仍然是唯一的。

但 EF(或 SQL Server 分别)拒绝更改,因为它逐记录进行,因此暂时违反了此约束。

是否有任何(EF 内置)机会告诉 SQL Server,在更新几条记录的操作期间,他不必担心约束,但之后?

我不需要任何提示/解决方法,例如在末尾“附加”序列号。

问题是:每当更新唯一索引上的多条记录时,在逐记录操作期间,索引可能会被违反,但之后(在事务结束时)一切都会好起来的。我们如何在 EF 6 中做到这一点?

亲切的问候, 伴侣

代码示例: 1.) 模型和上下文

public class Model
{
    [Key]
    public long Key { get; set; }

    [Index("MyUniqueIndex", IsUnique = true)]
    public long IndexField { get; set; }
}

public class ModelContext : DbContext
{
    public DbSet<Model> ModelDbSet { get; set; }

    public ModelContext()
        : base("name = ModelContext")
    {
        Database.Log = Console.Write;
    }
}

2.) 片段应用程序

private void button1_Click(object sender, EventArgs e)
    {
        CreateRecords();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        SwapIndexAndSave();
    }

    public static void CreateRecords()
    {
        using (ModelContext context = new ModelContext())
        {
            // Create two records
            // Record 1 has value 1 in the unique index field
            // Record 2 has value 2 in the unique index field
            Model newModel1 = new Model {IndexField = 1};
            context.ModelDbSet.Add(newModel1);

            Model newModel2 = new Model {IndexField = 2};
            context.ModelDbSet.Add(newModel2);

            context.SaveChanges();
        }
    }

    public static void SwapIndexAndSave()
    {
        using (ModelContext context = new ModelContext())
        {
            // Load both records
            List<Model> data = context.ModelDbSet.ToList();
            // Swap values in unique index field
            // Record 1 will get value 2 in the unique index field
            // Record 2 will get value 1 in the unique index field
            foreach (Model model in data)
            {
                model.IndexField = 3 - model.IndexField;
            }
            // SaveChanges crashes, because on updating the first record will
            // result in identically values for the unique index field on the database.
            context.SaveChanges();
        }
    }

【问题讨论】:

  • 不幸的是,到目前为止,SQL Server 不支持任何类型的deferrable constraints。最好的“解决方法”是编写一个 UPDATE 语句,一次性执行所有更改,而不是逐行执行。 SQL 与基于集合的逻辑一起工作很好

标签: sql-server entity-framework


【解决方案1】:

您为什么不尝试仅对给定事务禁用约束..

我的意思是, 1) 禁用约束 2) 将值更新到数据库 3) 启用约束

如果您需要这方面的更多信息,请告诉我

亲爱的朋友,

我觉得我解释得不好,你可以为一个表启用/禁用一个特定的约束

--禁用 CK_Customer_CustomerType 约束 ALTER TABLE Sales.Customer NOCHECK CONSTRAINT CK_Customer_CustomerType

--做某事

--启用 CK_Customer_CustomerType 约束 ALTER TABLE Sales.Customer CHECK CONSTRAINT CK_Customer_CustomerType

请检查 MSDN Link

【讨论】:

  • 我想让您知道:在这种情况下,您如何禁用/启用约束?并且(也许更糟):您如何在 SaveChanges 的覆盖中执行此操作,其中可能会发生多个记录更改(不仅是所描述的那些更改)?整个数据库中的所有唯一约束都可能在之前禁用并在之后启用......
  • --禁用 CK_Customer_CustomerType 约束 ALTER TABLE Sales.Customer NOCHECK CONSTRAINT CK_Customer_CustomerType --do something --启用 CK_Customer_CustomerType 约束 ALTER TABLE Sales.Customer CHECK CONSTRAINT CK_Customer_CustomerType
  • 这就是问题所在:我对有关表一无所知。在 SaveChanges 期间,我处理了许多更改跟踪器条目。所以我可能会为数据库中的每个表调用 ALTER TABLE。考虑到完美的宇宙,EF 或 DBMS 通过设置一个属性直接提供此功能...... :-( 并且为了使这个词变得完美:如果违反打开的约束,则丢弃/回滚更改。
  • 你能给我结构和你的示例代码吗...我想对其进行一些测试...如果你能提供一个示例就可以了
  • 禁用约束的问题是 a) 它需要您拥有相当多的权限 b) 它会影响数据库的 所有 用户,因为任何人都可以填充数据当它们被禁用时,它们将不符合约束。如此有效,仅当系统由单个用户使用时(至少在他们执行此活动的时间段内),这只是一种选择
猜你喜欢
  • 2017-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-16
  • 1970-01-01
  • 2013-02-02
相关资源
最近更新 更多