[英]SqlException: Cannot insert explicit value for identity column in table 'Ogretmenler' when IDENTITY_INSERT is set to OFF
[英]SqlException: Cannot insert explicit value for identity column in table [Table name] when IDENTITY_INSERT is set to OFF
我正在創建一個用於費用跟蹤的網站,當我發送一個新的 POST 請求調用AddNew
方法來添加一個新條目時,我收到此錯誤:
SqlException:當 IDENTITY_INSERT 設置為 OFF 時,無法為表“Accounts”中的標識列插入顯式值。 當 IDENTITY_INSERT 設置為 OFF 時,無法為表 'Categories' 中的標識列插入顯式值。
public class Entry
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Description { get; set; }
public decimal MoneyAmount { get; set; }
public virtual Account Account { get; set; }
public virtual Category Category { get; set; }
public string CreatedTimestamp { get; set; }
}
public class Account
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public virtual User User { get; set; }
//public byte[] BankApi { get; set; }
public decimal MoneyAmount { get; set; }
public string CreatedTimestamp { get; set; }
public virtual ICollection<Entry> Entries { get; set; }
}
public class Category
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public virtual EntryType EntryType { get; set; }
public virtual ICollection<Entry> Entries { get; set; }
}
public interface IEntryService
{
void AddNew(Entry entry);
}
public class EntryService : IEntryService
{
private DataContext _context;
public EntryService(DataContext context)
{
_context = context;
}
public void AddNew(Entry entry)
{
entry.CreatedTimestamp = DateTime.Now.ToString();
_context.Entries.Add(entry);
_context.SaveChanges();
}
}
這是我的郵遞員請求:
ID == 1 的帳戶和 ID == 1 的類別都已存在於各自的數據庫中。
此外,當我向 Account 數據庫插入值時,其方法與條目的AddNew
完全相同,它可以正常工作。
有誰知道這是關於什么的?
問題是您將具有關系的實體傳遞回服務器。 每個請求都由不同的數據庫上下文提供服務,因此雖然您的條目及其關聯的帳戶和類別看起來像實體,但它們不是。 它們是 DbContext 一無所知的反序列化 POCO 對象。 當您傳遞引用數據庫中已存在的其他實體的實體時,接收上下文不知道這些實體,因此它將它們解釋為新記錄並嘗試插入它們。
我的默認建議是永遠不要在客戶端和服務器之間傳遞實體。 這會導致從服務器到客戶端的序列化錯誤和性能問題,並使您的系統暴露於篡改,以及在從客戶端到服務器使用時插入錯誤或重復等問題。
要在沒有太多更改的情況下解決您的問題:
public void AddNew(Entry entry)
{
entry.CreatedTimestamp = DateTime.Now.ToString();
var account = _context.Accounts.Single(x => x.Id = entry.Account.Id);
var category = _context.Categories.Single(x => x.Id = entry.Category.Id);
entry.Account = account;
entry.Category = category;
_context.Entries.Add(entry);
_context.SaveChanges();
}
這將條目帳戶和類別與上下文已知的實例相關聯。
另一種方法是將傳遞回 DbContext 的帳戶和類別附加到。 這也可以,但它會使您的系統容易受到篡改。 傳回控制器的數據可以被客戶端機器上的調試工具或嗅探器截獲,其中可以更改消息中的數據,以您不希望的方式更改記錄及其相關記錄中的詳細信息。 如果出於任何原因,任何代碼最終將這些重新附加的實體設置為修改狀態,則這些更改將在 SaveChanges 上持久保存到數據庫中。 在處理多個分離的引用時,附加實體也很麻煩。 例如,如果您一次與親戚保存多條記錄。 當所有親戚都是唯一的時,附加每個都可以正常工作,但是如果沒有額外的邏輯來檢查每個人以查看是否已經附加了引用,則在嘗試對已附加(或加載)實體附加的第二個引用時,您可能會收到錯誤. 這意味着更多的代碼來檢查本地關聯並在找到時替換它。
我剛剛改變了條目模型
public class Entry
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Description { get; set; }
public decimal MoneyAmount { get; set; }
public virtual Account Account { get; set; }
public virtual Category Category { get; set; }
public string CreatedTimestamp { get; set; }
}
對此:
public class Entry
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Description { get; set; }
public decimal MoneyAmount { get; set; }
public int AccountId { get; set; }
public int CategoryId { get; set; }
public string CreatedTimestamp { get; set; }
}
現在似乎一切正常。 C# 發揮了它的魔力,並選擇 AccountId 和 CategoryId 作為外鍵。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.