实体框架中的增量字段取决于另一个字段的值

时间:2011-11-29 10:17:11

标签: entity-framework auto-increment

我是Entity Framework的新手,我在纯t-sql中很容易出问题。假设我们有3列的表。 Id(标识,主键),IdKind(int),Number(int)。列Nubmer依赖于IdKind列。此表中的数据应如下所示:

Id | IdKind |编号

1 | 1 | 1

2 | 1 | 2

3 | 1 | 3

4 | 2 | 1

5 | 2 | 2

6 | 2 | 3

如您所见,列号自动递增取决于IdKind。在t-sql中,我发现某些IdKind的max(Number)+ 1。一切都在一个事务中的一个存储过程中,因此Number的值对于IdKind是唯一的。

如何在Entity Framework中完成相同的操作。应在创建新对象或更改IdKind时计算Number的值。

2 个答案:

答案 0 :(得分:4)

我会使用数据库触发器并在EF映射中使用Number配置StoreGeneratedPattern.Computed属性,以通知EF此属性已在数据库中填充,并且必须在每次更新/插入后重新加载。

我也不会对每个新号码使用max()。相反,我会维护单独的表模拟序列。此表应包含每个序列的记录 - 在每个IdKind的案例记录中包含当前最大数量。您将选择单个记录并将其更新为包含新的最大数量,而不是选择聚合。使用此表必须与对实体的持久更改处于同一事务中。

答案 1 :(得分:2)

我遇到了同样的问题,但我在c#中解决了这个问题。

我应该有一个映射到表的实体:

public class MyEntity
{ 
     Kind IdKind{get; set;}
     int Number{get;set;}
}

我应该有辅助实体存储每种类型使用的最后一个数字。

public class LastNumber
{ 
     Kind IdKind{get;set;}
     int LastNumber{get;set;}
}

然后在向表中添加一行(MyEntity对象)之前,我应该使用LastNumberEntity的LastNumber字段计算正确的Number,其中Kind等于我的Kind值。

我们必须注意这个策略有一个并发问题,因为两个不同的线程可能同时添加同一种类的对象,这些线程将检查相同的LastNumberEntity以获取LastNumber值。这个问题在entityframework中有一个已知的解决方案。代码可能如下所示:

 public int GetNumber(Kind idKind)
    {
        using (var db = new MyDataContext())
        {
            var lastNumber = db.LastNumbers.Single(x=>x.IdKind == idKind);
            for (int attemps = 0; attemps < 10;)
            {
                try
                {
                    lastNumber.LastNumber++;
                    db.SaveChanges();
                    return lastNumber.LastNumber;
                }
                catch (DbUpdateConcurrencyException ex)
                {
                    attemps++;
                }
            }
        }

        throw new Exception("Many concurrency calls");
    }

此方法获取指定Kind的增量编号并处理并发问题,使用它,我们可以为每个MyEntity对象设置Number值。客户端代码可能如下所示:

var entity = new MyEntity();
var number = GetNumber(entity.IdKind);
entity.Number = number;
db.MyEntities.Add(entity);
db.SaveChanges();

此代码可以重构,使得setter成为私有代码,使工厂确保始终使用GetNumber方法创建实体并使用存储库来管理db。