sql-server – 在Entity Framework 4.1 Code First中手动生成主键的最佳方法是什么
|
在Entity Framework 4.1 Code First中手动生成主键的最佳方法是什么? 我正在编写ASP.NET MVC 3并使用存储库模式. 我目前使用以下代码按顺序生成密钥: 'Code First Class
Public Class Foo
<Key()>
<DatabaseGenerated(DatabaseGeneratedOption.None)>
Public Property iId As Integer
Public Property sBar As String
End Class
'Context Class
Public Class FooBarContext : Inherits DbContext
Public Property Foos As DbSet(Of Foo)
End Class
'Get the current Id
'Part of code in repository that stores Entity Foo.
Dim iCurrId as Integer = (From io In context.Foo
Select io.iId()).Max
Dim iNewId as Integer = iCurrId + 1
Foo.iId = iNewId
我的观点是(但不太可能)两个(或更多)用户将同时尝试保存实体Foo,因此将获得相同的ID并且插入将失败. 这是一个好方法,还是有更好的方法? 请注意,我不能(也不会)使用数据库生成的身份字段! 解决方法您的担忧是有效的 – 在经常使用的网站中,这种情况最有可能发生,解决方案并不容易.您可以使用@Mikecito所描述的客户端Guid,但它有很大的性能损失,我想您不想使用它.你现在这样做的方式非常糟糕,因为唯一的解决方案是将你的代码包装在单个可序列化的事务中 – 事务必须同时包含选择Id和保存记录.这将使您的InventoryObjects顺序访问,因为每个select max将锁定整个表,直到提交事务 – 在插入事务期间,没有其他人能够读取或写入数据到表.它不一定是很少访问的网站的问题,但它可以在经常访问的网站中没有GO.在当前设置中无法以不同方式执行此操作. 部分改进是使用单独的表来保存最大值存储过程以获取下一个值并在原子操作中增加存储的值 – (它实际上模拟来自Oracle的序列).现在唯一的复杂因素是如果你需要没有间隙的序列.例如,如果在保存新的InventoryObject时出现问题,则所选的Id将丢失,并且将在id的序列中创建间隙.如果您需要没有间隙的序列,则必须再次使用事务来获取下一个Id并保存记录,但这次您只会锁定序列表中的单个记录.从序列表中检索Id应尽可能接近保存更改,以最小化序列记录被锁定的时间. 以下是SQL Server的序列表和序列过程示例: CREATE TABLE [dbo].[Sequences]
(
[SequenceType] VARCHAR(20) NOT NULL,/* Support for multiple sequences */
[Value] INT NOT NULL
)
CREATE PROCEDURE [dbo].[GetNextSequenceValue]
@SequenceType VARCHAR(20)
AS
BEGIN
DECLARE @Result INT
UPDATE [dbo].[Sequences] WITH (ROWLOCK,UPDLOCK)
SET @Result = Value = Value + 1
WHERE SequenceType = @SequenceType
RETURN @Result
END
该表不需要首先按代码映射 – 您永远不会直接访问它.您必须创建自定义数据库初始化程序,以便在EF创建数据库时为您添加表和存储过程.您可以尝试类似于described here的方法.您还必须为序列添加初始化记录和起始值. 现在,您只需要在保存记录之前调用存储过程来获取值: // Prepare and insert record here
// Transaction is needed only if you don't want gaps
// This whole can be actually moved to overriden SaveChanges in your context
using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew,new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))
{
record.Id = context.Database.ExecuteStoreCommand("dbo.GetNextSequenceValue @SequenceType",new SqlParameter("SequenceType","InventoryObjects"));
context.SaveChanges();
} (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- sql-server – 使用SQL Server“FOR XML”:将结果数据类型
- sql-server – PK索引中列的顺序是否重要?
- SQL Server – 每个表的权限?
- redis中使用redis-dump导出、导入、还原数据实例
- sql-server-2005 – 如何使用Powershell枚举SQL Server角色
- sql-server – 在SQL Server上的聚簇索引,大表上的DELETE性
- sql数据库批量处理脚本
- SQLite教程(十四):C语言编程实例代码(2)
- SQL server使用自定义函数以及游标
- sql – 在Postgres jsonb中查询数组中的结构的正确索引是什
