我是实体框架的新手,我对纯T-SQL很容易的问题有问题。假设我们有3列的表。 id(身份,主键),idkind(int),数字(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的最大值(编号) + 1。一切都以一个交易中的一个存储过程为单位,因此IDKIND的数字值是唯一的。

如何在实体框架中完成相同的操作。创建新对象或更改IDKIND时,应计算数字值。

有帮助吗?

解决方案

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

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

其他提示

我遇到了同样的问题,但我在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字段计算出适当的数字,并等于我的善值。

我们必须注意,此策略有一个并发问题,因为两个不同的线程可能同时添加相同的对象,这些线程将检查相同的最后一个杂项以获取末尾值。这个问题在实体框架中具有已知解决方案。代码看起来像这样:

 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");
    }

此方法获得了指定类型的增量数并处理并发问题,使用它,我们可以为每个MERENTITY对象设置数字值。客户端代码看起来像这样:

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

可以重新制定此代码,使设置工具私有化,制造出工厂,以确保使用getNumber方法创建实体,并使用存储库来管理DB。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top