Entity Framework: Cập nhật, chèn hoặc xóa câu lệnh Store Store đã ảnh hưởng đến số lượng hàng không mong muốn (0). [đóng cửa]


324

Tôi đang sử dụng Entity Framework để điền vào điều khiển lưới. Đôi khi khi tôi cập nhật, tôi gặp lỗi sau:

Lưu trữ cập nhật, chèn hoặc xóa câu lệnh ảnh hưởng đến số lượng hàng không mong muốn (0). Các thực thể có thể đã được sửa đổi hoặc xóa kể từ khi các thực thể được tải. Làm mới các mục ObjectStateManager.

Tôi không thể tìm ra cách tái tạo này. Nhưng nó có thể có liên quan đến việc tôi thực hiện các bản cập nhật gần nhau như thế nào. Có ai nhìn thấy điều này hoặc có ai biết thông báo lỗi đề cập đến điều gì không?

Chỉnh sửa: Thật không may, tôi không còn tự do để tái tạo vấn đề tôi gặp phải ở đây, vì tôi đã rời khỏi dự án này và không nhớ liệu cuối cùng tôi có tìm ra giải pháp hay không, nếu một nhà phát triển khác đã khắc phục nó, hoặc nếu tôi làm việc xung quanh nó. Vì vậy, tôi không thể chấp nhận bất kỳ câu trả lời.


Tôi đã gặp lỗi này khi đưa ra chính sách Bảo mật cấp hàng của SQL Server cho phép cập nhật hàng thành trạng thái không thể đọc lại được (một vị từ LỌC độc quyền với vị từ BLOCK cho phép) . EntityFramework yêu cầu hàng cập nhật phải được đọc lại sau khi cập nhật nếu không nó cho rằng đó là lỗi đồng thời (ít nhất là khi sử dụng đồng thời lạc quan).
xr280xr

Vấn đề có thể là Phạm vi không chính xác cho DBContext bạn stackoverflow.com/questions/49154250/... (ví dụ này là dành cho ASPNET nhận dạng nhưng áp dụng cho bất kỳ ngữ cảnh)
Simon_Weaver

Bất kể bối cảnh của lỗi này là một ý tưởng tốt để đặt một điểm dừng ở bất cứ nơi nào mà bối cảnh đang được khởi tạo. Bạn có mong đợi nó sẽ được khởi tạo một lần khi bạn tải một trang web nhưng nó đạt điểm dừng đó 5 lần không? Sau đó, bạn có thể có một điều kiện cuộc đua. Nhìn vào Request.Uriđể xem URL yêu cầu thực tế. Trong trường hợp của tôi, tôi đã có một số logic theo dõi đang tấn công trang web của mình và tải không cần thiết bối cảnh từ DB (và đôi khi cũng cập nhật nó). Vì vậy, sau đó trang thực tế tôi đang gỡ lỗi có dữ liệu của nó bị cản trở bởi logic mã theo dõi ngu ngốc.
Simon_Weaver

thêm @ Html.AntiForgeryToken () trong chế độ xem
Vikas Sharma

Câu trả lời:


199

Đó là tác dụng phụ của một tính năng gọi là đồng thời lạc quan.

Không chắc chắn 100% về cách bật / tắt trong Entity Framework nhưng về cơ bản, điều bạn nói với bạn là giữa khi bạn lấy dữ liệu ra khỏi cơ sở dữ liệu và khi bạn lưu các thay đổi của mình, người khác đã thay đổi dữ liệu (Có nghĩa là khi bạn đi để lưu nó 0 hàng thực sự đã được cập nhật). Trong các thuật ngữ SQL, mệnh đề updatetruy vấn của chúng wherechứa giá trị ban đầu của mọi trường trong hàng và nếu 0 hàng bị ảnh hưởng, nó biết có gì đó không ổn.

Ý tưởng đằng sau đó là bạn sẽ không ghi đè lên một thay đổi mà ứng dụng của bạn không biết đã xảy ra - về cơ bản đó là một biện pháp an toàn nhỏ được .NET đưa vào trên tất cả các cập nhật của bạn.

Nếu nó nhất quán, tỷ lệ cược sẽ xảy ra trong logic của riêng bạn (EG: Bạn thực sự đang tự cập nhật dữ liệu theo một phương pháp khác giữa lựa chọn và cập nhật), nhưng đó có thể chỉ là điều kiện chạy đua giữa hai ứng dụng.


34
Điều này xảy ra trong môi trường một người dùng (trên máy dev của tôi) vì vậy tôi không nghĩ đó có thể là một điều kiện cuộc đua. Tôi liên kết với điều khiển lưới tùy chỉnh với EntityDataSource vì vậy tôi không chắc chắn chính xác những gì xảy ra đằng sau hậu trường, nhưng tôi không có thêm mã nào của riêng mình để sửa đổi các bảng. Có cách nào để thay đổi cài đặt đồng thời này không?
Strongopinions

3
Tôi nghĩ rằng bạn có thể trên cơ sở mỗi cột trong mô hình thực thể của mình (Nó nằm trong cửa sổ thuộc tính), nhưng điều này sẽ chỉ ngăn bạn nhìn thấy lỗi và nó vẫn không cập nhật bất cứ điều gì. Bạn có thể xem các lệnh SQL đi đến cơ sở dữ liệu của bạn (EG: SQL Server Profiler cho MSSQL) không? Bằng cách này, bạn có thể thấy bản cập nhật nào được tạo và sẽ có thể thấy lý do tại sao bản cập nhật đó không ảnh hưởng đến bất kỳ hàng nào.
fyjham

9
Nếu thực thể có thuộc tính dấu thời gian, thì hãy đảm bảo rằng bạn đã lưu nó trong chế độ xem của bạn và đảm bảo thực thể đó điền đúng dấu thời gian.
anIBMer

Tôi đã có một cột dấu thời gian và một khi tôi đã giải quyết nó, EF6.1 hoạt động như mong đợi, cảm ơn vì mẹo @anelBMer
JQII

3
Nếu bạn sử dụng dấu thời gian, đối tượng tje bạn muốn xóa cần bộ PK và Thuộc tính RowVersion để cập nhật thành công! Tôi đã thiết lập thuộc tính rowVersion (dấu thời gian), sau khi tôi đã gắn đối tượng vào DbSet tương ứng, đó là lý do tại sao nó không hoạt động. Làm tốt lắm!
Huyền thoại

394

Tôi gặp phải vấn đề này và nguyên nhân là do trường ID (khóa) của thực thể không được đặt. Do đó, khi bối cảnh lưu dữ liệu, nó không thể tìm thấy ID = 0. Hãy chắc chắn đặt điểm dừng trong câu lệnh cập nhật của bạn và xác minh rằng ID của thực thể đã được đặt.

Từ bình luận của Paul Bellora

Tôi đã có vấn đề chính xác này, do quên bao gồm đầu vào ID ẩn trong trang chỉnh sửa .cshtml


3
+1 Tôi đã gặp vấn đề tương tự và điều này đã giúp tìm ra giải pháp. Hóa ra tôi đã có [Bind (Exclude = "OrderID")] trong mô hình Đơn hàng của mình, điều này khiến giá trị của ID thực thể bằng 0 trên HttpPost.
Dhaust

2
Đó chính xác là những gì tôi đã thiếu. ID đối tượng của tôi là 0.
Azhar Khorasany

4
@ Html.HiddenFor (model => model.productID) - đã hoạt động hoàn hảo. Tôi đã thiếu sản phẩmID trên TRANG EDIT (MVC RAZOR)
Ravi Ram

2
Tôi đã có một vấn đề tương tự nhưng với một twist. Đối với tôi, vấn đề là tôi đã không thiết lập bảng sql chính xác. Trường khóa chính của tôi không được đặt thành tăng tự động. Vì vậy, EF sẽ gửi bản ghi mà tôi đang cố gắng chèn khóa w / oa, điều này tốt nếu bạn nhớ nói với sql rằng trường đó là trường Nhận dạng gia tăng tự động, mà tôi đã quên: <
Agile Noob

1
Vấn đề tương tự nhưng sử dụng khóa tổng hợp. Một trong những giá trị chính không được đặt.
obaylis 5/2/2015

113

Wow, rất nhiều câu trả lời, nhưng tôi đã gặp lỗi này khi tôi làm điều gì đó hơi khác mà không có ai khác đề cập.

Tóm lại, nếu bạn tạo một đối tượng mới và nói với EF rằng nó đã được sửa đổi bằng cách sử dụng EntityState.Modifiedthì nó sẽ đưa ra lỗi này vì nó chưa tồn tại trong cơ sở dữ liệu. Đây là mã của tôi:

MyObject foo = new MyObject()
{
    someAttribute = someValue
};

context.Entry(foo).State = EntityState.Modified;
context.SaveChanges();

Vâng, điều này có vẻ vô nghĩa, nhưng nó phát sinh bởi vì phương thức được đề cập đã foođược truyền cho nó đã được tạo ra trước đó, bây giờ nó chỉ someValuetruyền cho nó và footự tạo ra .

Dễ dàng sửa chữa, chỉ cần thay đổi EntityState.Modifiedđể EntityState.Addedhoặc thay đổi toàn bộ dòng để:

context.MyObject.Add(foo);

Cảm ơn đã đăng bài này. Đó cũng là vấn đề của tôi, tôi đã sao chép một số mã đang đặt Trạng thái thành EntityState.Modified.
đất sét

23

Tôi đã phải đối mặt với lỗi đáng sợ tương tự này ... :) Sau đó, tôi nhận ra rằng tôi đã quên thiết lập một

@Html.HiddenFor(model => model.UserProfile.UserId)

cho khóa chính của đối tượng được cập nhật! Tôi có xu hướng quên điều này đơn giản, nhưng rất quan trọng!

Nhân tiện: HiddenForlà cho ASP.NET MVC.


3
Điều đó có vẻ như là một lỗ hổng bảo mật, để lưu trữ UserIdtrong biểu mẫu, rất dễ bị tin tặc ... điều này nên được đưa vào sau đóHttpContext.Current.User.Identity.Name
Serj Sagan

@SerjSagan bạn đúng ... nhưng miễn là bạn thực hiện một số kiểm tra ở phía máy chủ để xác nhận UserId và Tên người dùng hiện tại bạn sẽ ổn.
Leniel Maccaferri

1
Quan điểm của tôi là tại sao thậm chí lưu trữ rằng HiddenForbạn sẽ cần lấy nó từ mọi nơi HttpContext... Tôi sẽ không đặt tài sản này ở dạng nào cả, điều này sẽ buộc tôi phải luôn đặt bên máy chủ ...
Serj Sagan

16

Kiểm tra xem bạn đã quên thuộc tính "DataKeyNames" trong GridView. đó là điều bắt buộc khi sửa đổi dữ liệu trong GridView

http://msdn.microsoft.com/en-us/l Library / system.web.ui.webcontrols.gridview.datakeOUNDes.aspx


+1. Giải pháp hoàn hảo và đơn giản cho tôi. Tôi đang ràng buộc GridView với EntityDataSource và không đặt khóa này thành khóa chính của tôi trên đối tượng.
Andez

Chúng tôi biết rằng Giao diện người dùng Kendo không hỗ trợ khóa tổng hợp, nhưng trong trường hợp tôi đã thêm cột mới kết hợp các khóa của mình với một khóa, điều gì sẽ xảy ra?
Branislav

15

Vấn đề được gây ra bởi một trong hai điều sau: -

  1. Bạn đã cố cập nhật một hàng với một hoặc nhiều thuộc tính là Concurrency Mode: Fixed.. và Đồng thời lạc quan đã ngăn dữ liệu được lưu. I E. một số thay đổi dữ liệu hàng giữa thời gian bạn nhận được dữ liệu máy chủ và khi bạn lưu dữ liệu máy chủ của mình.
  2. Bạn đã cố cập nhật hoặc xóa một hàng nhưng hàng không tồn tại. Một ví dụ khác về việc ai đó thay đổi dữ liệu (trong trường hợp này là xóa) ở giữa một lần truy xuất rồi lưu HOẶC bạn đang cố gắng cập nhật trường không phải là Danh tính (nghĩa là StoreGeneratedPattern = Computed) và hàng đó không tồn tại.

1
Điều này cũng có thể được gây ra nếu tất cả các thuộc tính đối tượng được gán, chúng được gán với cùng các giá trị như trước đây.
Serj Sagan

+1 cho cái thứ 2. Tôi đã có StoreGeneratedPotype = Không, thay đổi thành StoreGeneratedPotype = Danh tính đã giải quyết vấn đề. Cảm ơn
tkt986

12

Tôi đã gặp lỗi tương tự vì một phần của PK là cột thời gian và bản ghi được chèn được sử dụng DateTime. Bây giờ làm giá trị cho cột đó. Khung thực thể sẽ chèn giá trị với độ chính xác mili giây, và sau đó tìm giá trị mà nó vừa chèn cũng với độ chính xác mili giây. Tuy nhiên, SqlServer đã làm tròn giá trị thành độ chính xác thứ hai và do đó khung thực thể không thể tìm thấy giá trị chính xác mili giây.

Giải pháp là cắt bớt mili giây từ DateTime. Bây giờ trước khi chèn.


2
Chúng tôi đã có cùng một vấn đề ngoại trừ chúng tôi đã chèn vào một Datecột có DateTimegiá trị
adam0101

1
Tương tự ở đây. Chúng tôi đã có một bản ghi kho dữ liệu và đang sử dụng dấu thời gian như một phần của khóa. Dấu thời gian trong kho dữ liệu là SQL DateTime, nhưng dấu thời gian trong C # không khớp. Tôi đã thay đổi kiểu dữ liệu SQL thành DateTime2 (7), cập nhật mô hình EF và tất cả đã được sửa.
mmcfly

Thay đổi cột thành Datetime2 (7) cũng làm việc với tôi. Cảm ơn @mmcfly
Dzejms

10

Tôi đã gặp vấn đề tương tự và câu trả lời của @ webtrifusion đã giúp tìm ra giải pháp.

Mô hình của tôi đã sử dụng Bind(Exclude)thuộc tính trên ID của thực thể, điều này làm cho giá trị của ID thực thể bằng 0 trên HttpPost.

namespace OrderUp.Models
{
[Bind(Exclude = "OrderID")]
public class Order
{
    [ScaffoldColumn(false)]
    public int OrderID { get; set; }

    [ScaffoldColumn(false)]
    public System.DateTime OrderDate { get; set; }

    [Required(ErrorMessage = "Name is required")]
    public string Username { get; set; }
    }
}   

Vấn đề tương tự, vì lý do bảo mật, tôi có Bind (bao gồm = một số trường). ID không có trong danh sách. Ngoài ra tôi đã thêm nó như là một đầu vào ẩn. Phải xóa một cái gì đó được tạo bởi MVC hoặc ID hoàn toàn không có. Cảm ơn đã giúp đỡ.
MusicAndCode

10

Tôi có cùng một vấn đề, tôi nghĩ rằng đó là do RowVersion không có giá trị. Hãy kiểm tra xem bạn Id và bạn rowversionkhông null .

để biết thêm thông tin tham khảo hướng dẫn này

http://www.asp.net/mvc/tutorials/getting-started-with-ef-USE-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application


phiên bản hàng là null trong trường hợp của tôi
Prakash

Trong trường hợp của tôi, tôi đã vô tình xóa trường Id trong [Bind (Bao gồm = thuộc tính)]. Thêm nó trở lại và nó làm việc tốt.
Caverman

8

Tôi bắt đầu gặp lỗi này sau khi thay đổi từ mô hình đầu tiên sang mã đầu tiên. Tôi có nhiều luồng cập nhật cơ sở dữ liệu trong đó một số có thể cập nhật cùng một hàng. Tôi không biết tại sao tôi không gặp sự cố khi sử dụng mô hình trước, giả sử rằng nó sử dụng mặc định đồng thời khác.

Để xử lý nó ở một nơi biết các điều kiện theo đó nó có thể xảy ra, tôi đã thêm sự quá tải sau đến lớp DbContext của tôi:

using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;

public class MyDbContext: DbContext {
...
        public int SaveChanges(bool refreshOnConcurrencyException, RefreshMode refreshMode = RefreshMode.ClientWins) {
            try {
                return SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex) {
                foreach (DbEntityEntry entry in ex.Entries) {
                    if (refreshMode == RefreshMode.ClientWins)
                        entry.OriginalValues.SetValues(entry.GetDatabaseValues());
                    else
                        entry.Reload();
                }
                return SaveChanges();
            }
        }
}

Sau đó gọi là SaveChanges(true)bất cứ nơi nào áp dụng.


1
OK, mọi người khác đang đồng tình về vấn đề này, cho thấy cách họ có thể kích hoạt nó, v.v., nhưng câu trả lời này có một câu trả lời hay. Tôi sử dụng một mô hình cập nhật tiếp tục (không có nút lưu ở đây em bé) và đã nhận được điều này trên các bản cập nhật lưới khi luồng EF bị tụt lại phía sau và giải quyết nó. Công việc tuyệt vời tên tốt của tôi .. bạn làm cho tôi trông giống như một anh hùng - đứng trên vai người khổng lồ !!
Tony Trembath-Drake

Cũng giúp tôi, hãy xem cái này để có thêm tùy chọn- stackoverflow.com/a/13891724/4836581
Zvi Redler

7

Bạn cần bao gồm rõ ràng một BoundField của khóa chính. Nếu bạn không muốn người dùng nhìn thấy khóa chính, bạn phải ẩn nó qua css:

    <asp:BoundField DataField="Id_primary_key" ItemStyle-CssClass="hidden" 
HeaderStyle-CssClass="hidden" />

Trong đó 'hidden' là một lớp trong css có hiển thị được đặt thành 'none'.


1
hah, bạn đã cho tôi biết sự thật là tôi đã xóa trường id ẩn trong ASP.NET MVC. Cảm ơn @Paulo! :)
Tomasz Iniewicz

7

Trong khi chỉnh sửa bao gồm id hoặc khóa chính của thực thể dưới dạng trường ẩn trong dạng xem

I E

      @Html.HiddenFor(m => m.Id)

mà giải quyết vấn đề.

Ngoài ra, nếu mô hình của bạn bao gồm mục không được sử dụng, hãy bao gồm mục đó và đăng nó lên bộ điều khiển


7

Tôi cũng đã xem qua lỗi này. Vấn đề hóa ra là do một Trigger trên bàn tôi đang cố lưu lại. Trình kích hoạt đã sử dụng 'INSTEAD OF INSERT', có nghĩa là 0 hàng đã được chèn vào bảng đó, do đó xảy ra lỗi. May mắn thay trong trường hợp chức năng kích hoạt là không chính xác, nhưng tôi đoán đó có thể là một hoạt động hợp lệ mà bằng cách nào đó nên được xử lý trong mã. Hy vọng điều này sẽ giúp ai đó một ngày.


2
Thực thể có thể bị lừa tin rằng các hàng đã được thêm bằng cách trả về câu lệnh CHỌN (với cột khóa chính) từ trình kích hoạt.
jahu

1
Để mở rộng nhận xét của @jahu, tôi đã phải lấy id thực tế của mục mới được chèn để trả về từ trình kích hoạt của mình và tên cột phải khớp với cột nhận dạng của bảng kích hoạt (trong trường hợp của tôi, thực sự là một khung nhìn để nó không Tôi không có bản sắc riêng nhưng tôi đã lừa edmx để tin rằng nó đã làm). Trình kích hoạt của tôi đang thực hiện thao tác chèn vào một bảng riêng biệt, vì vậy tôi chỉ cần thêm dòng cuối cùng này vào trình kích hoạt của mình:SELECT SCOPE_IDENTITY() as MyViewId
DannyMeister


Trong trường hợp của tôi, tôi đang thực hiện thao tác xóa trên các thực thể trong bộ sưu tập con nhưng có một trình kích hoạt xóa đối với một trong các thực thể con khiến cho một thực thể con khác bị xóa. Điều này gây ra lỗi do các hàng N - 1 bị ảnh hưởng do trình kích hoạt xóa một trong các thực thể con trước khi khung thực thể cố gắng xóa nó.
skeletank

6

Tôi đã gặp vấn đề này trên một bảng bị thiếu khóa chính và có cột DATETIME (2, 3) (vì vậy "khóa chính" của thực thể là sự kết hợp của tất cả các cột) ... Khi thực hiện thao tác chèn dấu thời gian thời gian chính xác hơn (2018-03-20 08: 29: 51.8319154) đã bị cắt ngắn (2018-03-20 08: 29: 51.832) nên việc tra cứu trên các trường chính không thành công.


5

Tôi cũng đã có lỗi này. Có một số tình huống mà các Entity có thể không nhận thức được bối cảnh cơ sở dữ liệu thực tế mà bạn đang sử dụng hoặc mô hình có thể khác nhau. Đối với điều này, đặt: EntityState.Modified; vào EntityState. Đã thêm;

Để làm điều này:

if (ModelState.IsValid)
{
context.Entry(yourModelReference).State = EntityState.Added;
context.SaveChanges();
}

Điều này sẽ đảm bảo Thực thể biết bạn đang sử dụng hoặc thêm Trạng thái bạn đang làm việc. Tại thời điểm này, tất cả các Giá trị Mô hình chính xác cần được đặt. Cẩn thận không để mất bất kỳ thay đổi có thể đã được thực hiện trong nền.

Hi vọng điêu nay co ich.


1
bạn là một gurú! nó làm việc cho tôi
Hernaldo Gonzalez

5
  @Html.HiddenFor(model => model.RowVersion)

Chuyển đổi hàng của tôi là null, vì vậy phải thêm điều này vào chế độ xem giải quyết vấn đề của tôi


Không chuyển RowVersion từ Chế độ xem sang Hành động chỉnh sửa, cộng với tôi đã quên thực hiện ràng buộc mô hình cho RowVersion. Tại thời điểm bạn đang lưu đối tượng vào db, bạn cần giá trị trước đó của RowVersion gửi tới db cùng với đối tượng để kiểm tra đồng thời. Bạn mắc sai lầm ngớ ngẩn khi bạn cần mọi thứ nhanh hơn!
Dhanuka777

5

Dòng [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)]này đã lừa trong trường hợp của tôi:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;


[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int? SomeNumber { get; set; }

4

Chỉ cần đảm bảo bảng và biểu mẫu đều có khóa chính và edmx được cập nhật.

tôi thấy rằng bất kỳ lỗi nào trong quá trình cập nhật thường là do: - Không có khóa chính trong Bảng - Không có khóa chính trong Chế độ xem / biểu mẫu (ví dụ @Html.HiddenFor(m=>m.Id)


4

Tôi đã từng gặp vấn đề tương tự. Trong trường hợp của tôi, tôi đã cố cập nhật khóa chính, không được phép.


4

Tôi đã gặp lỗi này một cách rời rạc khi sử dụng một async phương thức. Đã không xảy ra kể từ khi tôi chuyển sang một phương pháp đồng bộ.

Lỗi lẻ tẻ:

[Authorize(Roles = "Admin")]
[HttpDelete]
[Route("file/{id}/{customerId}/")]
public async Task<IHttpActionResult> Delete(int id, int customerId)
{
    var file = new Models.File() { Id = id, CustomerId = customerId };
    db.Files.Attach(file);
    db.Files.Remove(file);

    await db.SaveChangesAsync();

    return Ok();
}

Hoạt động mọi lúc:

[Authorize(Roles = "Admin")]
[HttpDelete]
[Route("file/{id}/{customerId}/")]
public IHttpActionResult Delete(int id, int customerId)
{
    var file = new Models.File() { Id = id, CustomerId = customerId };
    db.Files.Attach(file);
    db.Files.Remove(file);

    db.SaveChanges();

    return Ok();
}

Mặc dù điều này đã giải quyết vấn đề của tôi, nhưng nó đã chỉ ra vấn đề tiềm ẩn được đề cập trước đó trong bài đăng này về các phiên bản PK & Row. Tôi đã bỏ qua việc thêm một bản đồ lược đồ cho một bảng mới phức tạp hơn nữa bởi thực tế PK không tuân theo quy tắc đặt tên. <Tên bảng> ID.
midohioboarder

3

Tôi đã gặp lỗi đó khi tôi đang xóa một số hàng trong DB (trong vòng lặp) và thêm các hàng mới trong cùng một bảng.

Các giải pháp cho tôi là, để năng động tạo ra một bối cảnh mới trong mỗi lần lặp


Tôi đã phải làm điều tương tự, vẫn không chắc tại sao vấn đề xảy ra ngay từ đầu, nhưng điều này hoạt động.
Jed Grant

3
    public void Save(object entity)
    {
        using (var transaction = Connection.BeginTransaction())
        {
        try
                {
                    SaveChanges();
                    transaction.Commit();
                }
                catch (OptimisticConcurrencyException)
                {
                    if (ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Deleted || ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Modified)
                        this.Refresh(RefreshMode.StoreWins, entity);
                    else if (ObjectStateManager.GetObjectStateEntry(entity).State == EntityState.Added)
                        Detach(entity);
                    AcceptAllChanges(); 
                    transaction.Commit();
                }
        }
    }

Bạn có thể vui lòng làm rõ 'cái này' đang đề cập ở đây và ObjectStateManager là gì không? Tôi đang thử điều này trong lớp kho lưu trữ cơ sở của chúng tôi nhưng gặp lỗi
Naomi

3

Điều này cũng sẽ xảy ra nếu bạn đang cố gắng chèn vào một tình huống ràng buộc duy nhất, tức là nếu bạn chỉ có thể có một loại địa chỉ cho mỗi chủ lao động và bạn cố gắng chèn một giây cùng loại với cùng một chủ nhân, bạn sẽ gặp vấn đề tương tự .

HOẶC LÀ

Điều này cũng có thể xảy ra nếu tất cả các thuộc tính đối tượng được gán, chúng được gán với cùng các giá trị như trước đây.

        using(var db = new MyContext())
        {
            var address = db.Addresses.FirstOrDefault(x => x.Id == Id);

            address.StreetAddress = StreetAddress; // if you are assigning   
            address.City = City;                   // all of the same values
            address.State = State;                 // as they are
            address.ZipCode = ZipCode;             // in the database    

            db.SaveChanges();           // Then this will throw that exception
        }

2

Nếu bạn đang cố gắng tạo ánh xạ trong tệp edmx của mình thành "Nhập khẩu chức năng", điều này có thể dẫn đến lỗi này. Chỉ cần xóa các trường để chèn, cập nhật và xóa trong Chi tiết ánh xạ cho một thực thể nhất định trong edmx của bạn và nó sẽ hoạt động. Tôi hy vọng tôi đã làm cho nó rõ ràng.


2

Tôi đã có ngoại lệ này khi đính kèm một đối tượng không tồn tại trong cơ sở dữ liệu. Tôi đã giả sử đối tượng được tải từ một bối cảnh riêng biệt, nhưng nếu đó là lần đầu tiên người dùng truy cập trang web, đối tượng được tạo từ đầu. Chúng tôi có các khóa chính tăng tự động, vì vậy tôi có thể thay thế

context.Users.Attach(orderer);

với

if (orderer.Id > 0) {
    context.Users.Attach(orderer);
}

2

Vâng, tôi có vấn đề tương tự. Nhưng điều này là do sai lầm của tôi. Trên thực tế tôi đã lưu một đối tượng thay vì thêm nó. Vì vậy, đây là xung đột.


2

Một cách để gỡ lỗi sự cố này trong môi trường Máy chủ Sql là sử dụng Trình cấu hình Sql kèm theo bản sao SqlServer của bạn hoặc nếu sử dụng phiên bản Express, hãy lấy bản sao Express Profiler miễn phí từ CodePlex theo liên kết dưới đây:

Trình bày nhanh

Bằng cách sử dụng Sql Profiler, bạn có thể có quyền truy cập vào bất cứ thứ gì đang được gửi bởi EF tới DB. Trong trường hợp của tôi, số tiền này là:

exec sp_executesql N'UPDATE [dbo].[Category]
SET [ParentID] = @0, [1048] = NULL, [1033] = @1, [MemberID] = @2, [AddedOn] = @3
WHERE ([CategoryID] = @4)
',N'@0 uniqueidentifier,@1 nvarchar(50),@2 uniqueidentifier,@3 datetime2(7),@4 uniqueidentifier',
@0='E060F2CA-433A-46A7-86BD-80CD165F5023',@1=N'I-Like-Noodles-Do-You',@2='EEDF2C83-2123-4B1C-BF8D-BE2D2FA26D09',
@3='2014-01-29 15:30:27.0435565',@4='3410FD1E-1C76-4D71-B08E-73849838F778'
go

Tôi đã sao chép nó vào một cửa sổ truy vấn trong Sql Server và thực hiện nó. Chắc chắn, mặc dù nó đã chạy, 0 bản ghi đã bị ảnh hưởng bởi truy vấn này do đó lỗi được trả về bởi EF.

Trong trường hợp của tôi, sự cố được gây ra bởi CategoryID.

Không có CategoryID được xác định bởi ID EF được gửi đến cơ sở dữ liệu do đó 0 bản ghi bị ảnh hưởng.

Mặc dù đây không phải là lỗi của EF mà là lỗi không hợp nhất "??" tuyên bố trong Trình điều khiển xem đang gửi vô nghĩa xuống tầng dữ liệu.


2

Không có câu trả lời nào ở trên bao gồm hoàn cảnh của tôi và giải pháp cho nó.

Mã lỗi được ném trong bộ điều khiển MVC5:

        if (ModelState.IsValid)
        {
            db.Entry(object).State = EntityState.Modified; 
            db.SaveChanges(); // line that threw exception
            return RedirectToAction("Index");
        }

Tôi đã nhận được ngoại lệ này khi tôi lưu một đối tượng khỏi chế độ xem Chỉnh sửa. Lý do nó ném nó là vì khi tôi quay lại để lưu nó, tôi đã sửa đổi các thuộc tính hình thành khóa chính trên đối tượng. Do đó, việc đặt trạng thái của nó thành Đã sửa đổi không có ý nghĩa gì với EF - đó là một mục mới, không phải là mục đã lưu trước đó.

Bạn có thể giải quyết vấn đề này bằng cách A) sửa đổi cuộc gọi lưu thành Thêm đối tượng hoặc B) chỉ không thay đổi khóa chính khi chỉnh sửa. Tôi đã làm B).


2

Khi câu trả lời được chấp nhận cho biết " nó sẽ không ghi đè lên một thay đổi mà ứng dụng của bạn không biết đã xảy ra ", tôi đã hoài nghi vì đối tượng của tôi mới được tạo. Nhưng sau đó nó bật ra, có một INSTEAD OF UPDATE, INSERT- TRIGGERbảng đính kèm bảng đang cập nhật một cột được tính toán của cùng một bảng.

Khi tôi thay đổi AFTER INSERT, UPDATEnó, nó hoạt động tốt.


2

Điều này xảy ra với tôi do sự không phù hợp giữa datetime và datetime2. Kỳ lạ thay, nó hoạt động tốt trước khi một người thử nghiệm phát hiện ra vấn đề. Mô hình Mã đầu tiên của tôi bao gồm DateTime là một phần của khóa chính:

[Key, Column(Order = 2)]  
public DateTime PurchasedDate { get; set; } = (DateTime)SqlDateTime.MinValue;

Cột được tạo là cột datetime. Khi gọi SaveChanges, EF đã tạo SQL sau:

-- Region Parameters
DECLARE @0 Int = 2
DECLARE @1 Int = 25
DECLARE @2 Int = 141051
DECLARE @3 DateTime2 = '2017-07-27 15:16:09.2630000' --(will not equal a datetime value)
-- EndRegion
UPDATE [dbo].[OrganizationSurvey]
SET [OrganizationSurveyStatusId] = @0
WHERE ((([SurveyID] = @1) AND ([OrganizationID] = @2)) AND ([PurchasedDate] = @3))

Bởi vì nó đã cố khớp một cột datetime với giá trị datetime2, nó không trả về kết quả nào. Giải pháp duy nhất tôi có thể nghĩ đến là thay đổi cột thành datetime2:

[Key, Column(Order = 2, TypeName = "DateTime2")]  
public DateTime PurchasedDate { get; set; } = (DateTime)SqlDateTime.MinValue;

1
Sự kì lạ của nó làm việc so với không làm việc đã làm với định dạng cơ bản / cơ sở của datetimevs datetime2. Về cơ bản, một số giá trị mili giây sẽ đánh giá khớp, một số khác thì không. Điều tương tự cũng xảy ra với tôi và tôi cũng chuyển sang DateTime2.
xr280xr

+1 Tôi ước tôi có thể +100 cho cái này cho bạn. Tôi sau khi tìm hiểu xung quanh nhiều nơi, cuối cùng tôi đã tìm thấy điều này và nhận ra rằng, thực sự, tôi đã có một Thời gian là một phần của khóa chính của mình. Vâng, điều này thực sự đã sửa nó. Tôi đã cập nhật cột thành Datetime2 và nó đã hoạt động. Bây giờ, thịt bò của tôi là với Entity Framework để đưa ra một truy vấn ngu ngốc như vậy cho điều này buộc tôi phải làm điều này.
Bắt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.