2011-11-29 50 views
2

我是实体框架中的新成员,并且在纯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来说是唯一的。

如何在实体框架中实现相同。在创建新对象或更改IdKind时应计算数值的值。

回答

4

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

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

0

我有同样的问题,但我解决了它在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字段的正确数量等于我的一种价值。

我们必须注意到,这个策略有一个并发问题,因为两个不同的线程可能会同时添加同一个对象,那些线程将检查相同的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"); 
    } 

这种方法获取指定类递增数字和处理并发问题,使用它,我们可以设置每个myEntity所对象的数值。客户端代码可能看起来是这样的:

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

这个代码可以重构,使制定者专用,使一家工厂,以确保始终使用的是GetNumber方法和使用存储库来管理数据库中创建的实体。

相关问题