2015-10-19 24 views
6

Tôi đang sử dụng Entity Framework 6 và cơ sở dữ liệu SQLite (System.Data.SQLite.EF6), nhưng tôi không thể tạo mục nhập có cùng khóa chính ngay lập tức sau khi xóa nó. Ví dụ:Entity Framework 6 và SQLite - không thể tạo mục nhập có PK mục nhập bị xóa trước

mô hình của tôi về thực thể:

public class Person 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.None)] 
    public int Id { get; set; } 

    public int Name { get; set; } 
} 

BƯỚC:

1) Tôi chèn trường hợp của PERSON1 tổ chức này (với Id = 1) vào bảng của tôi về người.

using (var context = new MyDbContext()) 
{ 
    context.Create(person1); 
    await context.SaveChangesAsync(); 
} 

2) Afters một số tome tôi xóa toàn bộ bảng Người có:

using (var context = new MyDbContext()) 
{ 
    await context.Database.ExecuteSqlCommandAsync(string.Format("DELETE FROM `PersonModels`")); 
    await context.SaveChangesAsync(); 
} 

3) Tôi cố gắng thêm vào với khóa chính tương tự như nhập từ bước 1: viên2 (với Id = 1)

using (var context = new MyDbContext()) 
{ 
    context.Create(person2); 
    await context.SaveChangesAsync(); 
} 

Nhưng ở bước 3, SaveChangesAsync() không thành công với

System.InvalidOperationException: Các thay đổi đối với cơ sở dữ liệu đã được cam kết thành công, nhưng đã xảy ra lỗi khi cập nhật ngữ cảnh đối tượng. ObjectContext có thể ở trạng thái không nhất quán. Thông báo ngoại lệ bên trong: Lưu hoặc chấp nhận thay đổi không thành công vì nhiều hơn một thực thể thuộc loại 'DbModels.PersonModel' có cùng giá trị khóa chính.

Khi tôi thêm một số mục nhập khác sau khi xóa bảng (với khóa chính khác) và sau đó thêm mục nhập từ bước 1, nó hoạt động tốt và cả hai mục được lưu mà không có ngoại lệ.

Tôi đã thêm điểm ngắt trực tiếp trước khi tạo mục nhập mới (sau khi bảng được xóa) và kiểm tra bảng Persons bởi công cụ và bảng bên ngoài trống (vì vậy không có mục nhập nào có id = 1).

UPDATE: Extended DbContexte + thực hiện phương pháp Tạo của tôi:

public DbSet<PersonModel> Persons { get; set; } 

    public T Create<T>(T entity) 
     where T : class 
    { 
     try 
     { 
      GetDbSetForType<T>().Add(entity); 
      return entity; 
     } 
     catch (Exception ex) 
     { 
      return default(T); 
     } 
    } 

    private DbSet<T> GetDbSetForType<T>() 
     where T : class 
    { 
     var type = typeof(T); 

     if (type == typeof(PersonModel)) return Persons as DbSet<T>; 
     //...my other types 
     throw new Exception("Type not found in db"); 
    }  
+0

ngữ cảnh.Create (person2) - đây có phải là phương pháp của riêng bạn không? Bởi vì tôi không nhớ EF có nó. Nếu vậy - bạn có thể hiển thị nó? – Toddams

+0

@Toddams oh, xin lỗi, tôi đã thêm phần thân của phương thức Create của tôi vào câu hỏi –

+0

Nếu bạn xóa tất cả các mục từ PersonModels, bạn có thể sử dụng nó: 'await context.Database.ExecuteSqlCommandAsync (string.Format (" TRUNCATE TABLE 'PersonModels' "));' Điều đó có hiệu quả với bạn không? – LocEngineer

Trả lời

0

bối cảnh cơ sở dữ liệu EF duy trì một danh sách các đối tượng mà nó lấy từ cơ sở dữ liệu trong bộ nhớ cho đến khi nó bị phá hủy hoặc bốc dỡ.

using (var ctx = new MyDbContext()) 
{ 
    var person1 = new Person { Id = 1 }; 
    ctx.Persons.Add(person1); 
    await ctx.SaveChangesAsync(); 

    await context.Database.ExecuteSqlCommandAsync(string.Format("DELETE FROM `PersonModels`")); 

    // This is the secret 
    ((IObjectContextAdapter)ctx).ObjectContext.Detach(person1); 

    ctx.Persons.Add(person1) 
    await ctx.SaveChangesAsync(); 

} 
+0

Cảm ơn, nhưng tôi đang sử dụng các ngữ cảnh riêng biệt (sau khi tôi xóa bảng Persons, tôi bỏ bối cảnh và tạo một thể hiện ngữ cảnh mới để thêm mục nhập). Ngoài ra, ((IObjectContextAdapter) ctx của tôi) .ObjectContext không chứa "Persons" (Tôi chỉ có tài sản Persons trong việc triển khai DbContext -> 'DbSet Persons', nhưng DbSet không có Detach().) –

+0

I chắc chắn không thể tái tạo vấn đề trong các trường hợp bạn mô tả. Tôi cũng đã cập nhật mẫu mã 'Detach'. –

Các vấn đề liên quan