当前正在使用Entity Framework 5开发ASP.Net MVC 4应用程序。在初始开发阶段使用了CodeFirst。但是现在已经禁用了自动迁移功能,并直接使用SSMS和编写POCO来设计新表。一切都很好。
最近,在生产中发现了一个奇怪的问题。最初设计的表之一中的记录使自动递增标识值跳过了900多个数字。在过去3个月中,这已经发生3次。在本地调试应用程序,但无法复制。没有观察到任何模式或趋势。
型号:
public class Enquiry
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public Int64 EnquiryId { get; set; }
[Required]
public int UserId { get; set; }
[Required]
public byte Bid { get; set; }
...
[Required]
public DateTime Created { get; set; }
[Required]
public DateTime Modified { get; set; }
}
public class EnquiryDetail
{
[Key]
public Int64 EnquiryId { get; set; }
[Required]
public int CreditScore { get; set; }
[Required]
public byte BidMode { get; set; }
public virtual Enquiry Enquiry { get; set; }
}
DBContext:
public class EscrowDb : DbContext
{
public EscrowDb()
: base("name=DefaultConnection")
{
}
public DbSet<Enquiry> Enquiries { get; set; }
public DbSet<EnquiryDetail> EnquiryDetails { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<EnquiryDetail>()
.HasRequired<Enquiry>(ed => ed.Enquiry)
.WithRequiredDependent(e => e.EnquiryDetail);
}
}
Controller :
[Authorize]
public class EnquiryController : Controller
{
private EscrowDb _db = new EscrowDb();
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(EnquiryViewModel core)
{
var enquiry = new Enquiry();
// Some code to set properties using passed ViewModel
...
var enquiryDetail = new EnquiryDetail();
// Some code to set properties using passed ViewModel
...
enquiry.EnquiryDetail = enquiryDetail;
_db.Enquiries.Add(enquiry);
_db.SaveChanges();
}
}
到目前为止,所有这些代码都能正常工作,除了标识值偶尔会被几乎1000个数字的大间隙跳过。
有人遇到过这种问题吗?请分享您的想法。
最佳答案
如果您需要消除这些差距,那么您可能不走运。
在开发/测试新应用程序时,我自己遇到了这个问题。我根据对sql server 2012的了解来了解sql azure中的情况。我无法找到有关sql azure的任何文档。
从我阅读的内容来看,这是IMO的一个错误。在Sql Server 2012中,Microsoft添加了创建序列的功能。序列记录以1000个块为单位使用的值。因此,假设您的序列正在执行中……1,2,3,4,5 ...,然后sql server重新启动。好了,该序列已经保存了以下事实:块1-1000已经被使用过,因此它将跳转到下一个1000...。因此,下一个值为1001、1002、1003、1004...。在使用序列时插入,但会导致异常的间隔。您的序列有一个解决方案。指定序列时,请添加“NOCACHE”参数,以免一次不保存1000个块。 See here for more documentation.
这成为一个问题的地方是,标识列似乎已更改为使用相同的范例。因此,当您的服务器(或在这种情况下,您的sql azure实例)重新启动时,您的标识列可能会出现较大的间隙(1000),因为它会将大型块缓存为“已用”。 sql server 2012对此有一个解决方案。您可以指定启动标志t272以将您的身份恢复为使用旧的sql server 2008 r2范例。问题是我不知道(可能不可能)如何在sql Azure中指定它。找不到文档。 See this thread for more details on sql server 2012.
Check the documentation of identity here in the msdn.特别是“服务器重新启动或其他故障后的连续值”部分。它说的是:
Consecutive values after server restart or other failures –SQL Server might cache identity values for performance reasons and some of the assigned values can be lost during a database failure or server restart. This can result in gaps in the identity value upon insert. If gaps are not acceptable then the application should use a sequence generator with the NOCACHE option or use their own mechanism to generate key values.
因此,如果您需要连续的值,则可以尝试使用nocache指定一个序列,而不要依赖您的身分列。自己还没有尝试过,but sounds like you'll have trouble getting this to work with entity framework.
抱歉,如果这样做没有太大帮助,但至少是有关您的经验的一些信息。
关于sql-server - Windows Azure SQL数据库-“身份自动增加”列会跳过值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17012339/