English 中文(简体)
如何以人工方式在实体框架4.1准则中产生主要要素
原标题:What is the best way to manually generate Primary Keys in Entity Framework 4.1 Code First

如何以人工方式在实体框架4.1准则中产生主要要素?

I am programming ASP.NET MVC 3 and I use a repository pattern.

I currently generate keys in a sequential order by using the code below:

 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”将获得同样的识别资料,而“Foo”这一短语将失败。

这种做法是好的还是更好的?

请不要让CNNOT(而且不会)使用一个产生身份的数据库!

最佳回答

Here is what I ended up using. This code is based on the post by Ladislav Mrnka, but modified to work with DbContext.

储存序列信息的模式(不要忘记在你的情况下添加这种信息作为德国统计局)。

<Table("tSequences")>
Public Class Sequence
    <Key()>
    <DatabaseGenerated(DatabaseGeneratedOption.None)>
    <Display(Name:="Model name", Order:=1)>
    Public Property sModelName As String

    <Required()>
    <Display(Name:="Current Primary key value", AutoGenerateField:=False, Order:=2)>
    Public Property iCurrentPKeyValue As Integer
End Class

• 启动数据库,建立仓储程序,以获取和自动收集顺序。

Public Class DBInitializer
    Inherits CreateDatabaseIfNotExists(Of Context)

    Protected Overrides Sub Seed(context As Context)
         Create stored procedure to hold
        Dim sStoredProcSQL As String = "CREATE PROCEDURE [dbo].[spGetNextSequenceValue]" & vbCrLf & _
                                        "@sModelName VARCHAR(30)" & vbCrLf & _
                                        "AS BEGIN" & vbCrLf & _
                                        "DECLARE" & vbCrLf & _
                                        "@Result INT" & vbCrLf & _
                                        "UPDATE [dbo].[tSequences] WITH (ROWLOCK, UPDLOCK)" & vbCrLf & _
                                        "SET @Result = iCurrentPKeyValue = iCurrentPKeyValue + 1" & vbCrLf & _
                                        "WHERE sModelName = @sModelName" & vbCrLf & _
                                        "RETURN @Result" & vbCrLf &
                                        "END"

        context.Database.ExecuteSqlCommand(sStoredProcSQL)
    End Sub
End Class

通过管理所储存的程序,为实体Foo找到一个新的钥匙(i NewKey)。

Dim iNewKey As Integer

Using scope = New TransactionScope(TransactionScopeOption.RequiresNew, New TransactionOptions() With { _
    .IsolationLevel = IsolationLevel.ReadCommitted _
    })
    iNewKey = context.Database.SqlQuery(Of Integer)("DECLARE @return_value int" & vbCrLf & _
                                                    "EXEC @return_value = [dbo].[spGetNextSequenceValue]" & vbCrLf & _
                                                    "@sModelName =  Foo " & vbCrLf & _
                                                    "SELECT  Return Value  = @return_value").ToList().First()
 Indicate that all operations are completed.
    scope.Complete()

    context.SaveChanges()
End Using
问题回答

你的关切是有效的——在经常使用的网站上,这种情况很可能发生,解决办法并不容易。 如@Mikecito所述,你可以使用客户栏目<> 准则>,但业绩受到重大打击,我猜测你不想使用。

目前,你这样做的方式非常糟糕,因为唯一的解决办法是把你的代码列入单一的可序列交易——交易必须既包含选择Id,又保留记录。 这将使查阅<代码>InventoryObjects sequential,因为每项选择的最高限额在交易发生之前将锁定整个表格——在交易中没有人能够读到或书写数据。 在很少访问现场时,这并不必然是一个问题,但是在经常访问的现场,它可能是诺琴。 在你目前设立的机构中,没有任何办法可以不同地这样做。

The partial improvement is using separate table to hold max value + stored procedure to get the next value and increment the stored value in atomic operation - (it actually simulates sequences from Oracle). Now the only complication is if you need the sequence without gaps. For example if something goes wrong with saving of new InventoryObject the selected Id will be lost and it will create a gap in the id s sequence. If you need sequence without gaps you must again use transaction to get the next Id and save the record but this time you will only lock single record in sequence table. Retrieving the Id from sequence table should be as close to saving changes as possible to minimize time when sequence record is locked.

这里是服务器序列表和序列程序的样本:

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

表格不需要先用代码绘制,你永远不能直接查阅。 您必须创建海关数据库,以便在电子格式建立一个数据库时,增加表格和储存程序。 https://stackoverflow.com/questions/5701608/unique-key-with-ef-code-first/5701702#5701702>。 您还必须增加具有开端价值的首创记录。

Now you only need to call stored procedure to get a value before you are going to save the record:

// 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();
}

Can you use a GUID instead of an INT? If so, you can just use

System.Guid.NewGuid().ToString()

If not, you ll need to lock the thread or the table to avoid two inserts using the same ID.





相关问题
Is Shared ReadOnly lazyloaded?

I was wondering when I write Shared ReadOnly Variable As DataType = New DataType() Or alternatively Shared ReadOnly Variable As New DataType() Is it lazy loaded or as the instance initializes? ...

Entertaining a baby with VB.NET

I would like to write a little application in VB.NET that will detect a baby s cry. How would I get started with such an application?

Choose Enter Rather than Pressing Ok button

I have many fields in the page and the last field is a dropdown with list of values. When I select an item in a dropdown and press Enter, it doesn t do the "Ok". Instead I have to manually click on Ok ...

ALT Key Shortcuts Hidden

I am using VS2008 and creating forms. By default, the underscore of the character in a textbox when using an ampersand is not shown when I run the application. ex. "&Goto Here" is not ...

Set Select command in code

On button Click I want to Set the Select command of a Gridview. I do this and then databind the grid but it doesn t work. What am i doing wrong? protected void bttnView_Click(object sender, ...

Hover tooltip on specific words in rich text box?

I m trying to create something like a tooltip suddenly hoovering over the mouse pointer when specific words in the richt text box is hovered over. How can this be done?

热门标签