1

我遇到了通過DbContext.Add(...)方法添加新實體的問題。在DbContext.SaveChanges()上,我得到一個DbUpdateConcurrencyException。我正在嘗試向數據庫中插入數據。我是應用程序中唯一的開發人員,運行localhost,並且數據庫表是純粹的。沒有用戶。只有我。添加DbUpdateConcurrencyException

這並沒有幫助,雖然這是類似的:
Entity Framework 6 DbUpdateConcurrencyException When Adding New Rows To Database

我使用的是每個請求一個的DbContext。就像這樣:
One DbContext per request in ASP.NET MVC (without IOC container)

我退出由實體框架是這樣生成的SQL語句:
https://stackoverflow.com/a/20751723/2088914

這裏的模型(代碼首先,與遷移)。當我發佈時,我只提供助理,角色,轉讓人和刪除的標誌。行ID被自動設置爲0,因爲我沒有從客戶端提供它,日期爲默認值,以及,我然後填充在服務器 - 所有預期的東西:

public class Permission { 

    [Column("row_id")] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int RowId { get; set; } 

    [Key] 
    [StringLength(10)] 
    [Column("associate_nt_id", Order = 0)] 
    [Required] 
    public string AssociateNtId { get; set; } 

    [Key] 
    [Column("role_name", Order = 1)] 
    [StringLength(50)] 
    [Required] 
    public string RoleName { get; set; } 

    [Key] 
    [Column("eff_ts", Order = 2)] 
    [Required] 
    public DateTime EffectiveTimestamp { get; set; } 

    [StringLength(10)] 
    [Column("assignor_nt_id")] 
    [Required] 
    public string RoleAssignorNtId { get; set; } 

    [Column("deleted")] 
    [Required] 
    public bool Deleted { get; set; } 

} 

我有與柱方法,該方法被成功地由角溫泉訪問,並且模型的web API控制器被填充:

[HttpPost] 
[Route("")] 
[Require(Roles.admin)] 
public Permission Post(Permission permission) { 
    permission.EffectiveTimestamp = DateTime.Now; 
    MAPDB.Current.Permissions.Add(permission); 
    MAPDB.Current.Database.Log = s => { 
     Debug.WriteLine(s); 
    }; 
    MAPDB.Current.SaveChanges(); 
    return permission; 
} 

我在調試在Visual Studio 2015年在此潤的錯誤消息:
enter image description here

下面是實體框架生成的SQL:

INSERT [dbo].[_permissions]([associate_nt_id], [role_name], [eff_ts], [assignor_nt_id], [deleted]) 
VALUES (@0, @1, @2, @3, @4) 
SELECT [row_id] 
FROM [dbo].[_permissions] 
WHERE @@ROWCOUNT > 0 AND [associate_nt_id] = @0 AND [role_name] = @1 AND [eff_ts] = @2 
-- @0: 'associate' (Type = String, Size = 10) 
-- @1: 'user' (Type = String, Size = 50) 
-- @2: '9/20/2017 12:49:05 PM' (Type = DateTime2) 
-- @3: 'assignor' (Type = String, Size = 10) 
-- @4: 'True' (Type = Boolean) 
-- Executing at 9/20/2017 12:49:05 PM -05:00 
-- Completed in 24 ms with result: SqlDataReade 
-- Closed connection at 9/20/2017 12:49:05 PM -05:00 

似乎在記錄器已經執行,並且聲明這正是我所期望的,除了沒有數據庫插入發生。如果我將該語句從記錄器中取出,請填寫參數並通過sql客戶端執行它,它將起作用並返回所創建的行ID。我不明白問題所在 - 沒有發生併發情況,沒有列丟失/不應該添加,沒有無效參數,沒有問題將列映射到對象屬性,沒有關鍵違規,沒有標識列問題。

我該如何獲得實體框架來插入這個新對象(沒有吞嚥異常)?

謝謝你的幫助。

+1

您還可以將'RowId'標記爲主鍵,但將當前使用的3個字段的主聚簇索引作爲鍵。您還必須手動更改生成的遷移腳本。 – Igor

+0

@Igor這是一個有用的建議。現在我的工作方式如下,但我想知道如果我按照你的意思去做,我可能不得不這樣做:更改列類型並切換索引和鍵。謝謝。 –

回答

2

最有可能的問題是由PK(EffectiveTimestamp)的DateTime部分引起的。插入記錄,但SELECT未找到它,因爲默認情況下,EF將DateTime屬性映射到datetime列,而從日誌中可以看到,參數類型爲datetime2,它具有更高的精度,因此它會被截斷當存儲到表格列時,因此不會與選擇過濾器的[eff_ts] = @2部分相匹配。

要查看是否是這樣的話,你可以嘗試微調的時間價值:

// ... 
var time = DateTime.Now; 
permission.EffectiveTimestamp = new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, time.Second); 
// ... 

如果這樣的作品(如我期望的那樣),你可能會考慮更改數據庫列類型:

[Key] 
[Column("eff_ts", Order = 2, TypeName="datetime2")] 
[Required] 
public DateTime EffectiveTimestamp { get; set; } 
+0

是的,這工作。具體來說,我對'TypeName =「datetime2」'做了你所說的,並且一旦完成就刪除'DateTime.Now'截斷。非常感謝。 –