Entity Framework: "Зберігати операцію оновлення, вставлення чи видалення вплинуло на несподіване число рядків (0)." [зачинено]


324

Я використовую Entity Framework для заповнення управління сіткою. Іноді під час оновлення я отримую таку помилку:

Заява про оновлення, вставлення чи видалення вплинула на несподіване число рядків (0). Суб'єкти, можливо, були змінені або видалені з моменту завантаження об'єктів. Оновити записи ObjectStateManager.

Я не можу зрозуміти, як це відтворити. Але це може мати щось спільне з тим, наскільки близько я роблю оновлення. Хтось бачив це чи хтось знає, на що посилається повідомлення про помилку?

Редагувати: На жаль, я більше не маю права відтворювати проблему, яку я мав тут, тому що я відійшов від цього проекту і не пам’ятаю, чи знайшов я врешті-решт рішення, чи вирішив його інший розробник чи я працював над ним. Тому я не можу приймати жодної відповіді.


Цю помилку я отримав при введенні політики безпеки SQL Server Row Level, яка дозволила оновити рядок у стан, який не можна було прочитати назад (ексклюзивний предикат FILTER з дозволеним предикатом BLOCK) . EntityFramework вимагає зчитувати оновлений рядок після оновлення, інакше він вважає, що це помилка паралельності (принаймні, при використанні оптимістичної одночасності).
xr280xr

Проблема може бути неправильне визначення сфери охоплення для DbContext stackoverflow.com/questions/49154250 / ... (цей приклад для ASPNET ідентичності , але застосовується для будь-якого контексту)
Simon_Weaver

Незалежно від контексту цієї помилки, корисно поставити точку перерви де завгодно, що контекст інстанціюється. Ви очікували, що вона буде завантажена колись під час завантаження веб-сторінки, але вона 5 разів потрапляє на цю точку розриву? Тоді у вас, ймовірно, є стан гонки. Подивіться, Request.Uriщоб побачити фактичну URL-адресу запиту. У моєму випадку я мав деяку логіку відстеження, яка потрапляла на мій сайт і зайво завантажувала контекст із БД (а також час від часу оновляючи його). Тоді фактична сторінка, на якій я налагоджувалась, мала її дані, пронизані дурною логікою коду відстеження.
Simon_Weaver

add @ Html.AntiForgeryToken () у перегляді
Vikas Sharma

Відповіді:


199

Це побічний ефект функції, яка називається оптимістичною одночасністю.

Не на 100% впевнений, як увімкнути / вимкнути це в Entity Framework, але в основному те, що воно вам говорить, це те, що між тим, як ви схопили дані з бази даних, і коли ви зберегли зміни, хтось інший змінив дані (Що означало, коли ви пішли щоб зберегти його 0 рядків фактично оновлено). У термінах SQL, їх updateзапит whereмістить первісне значення кожного поля в рядку, і якщо це впливає на 0 рядків, воно знає, що щось пішло не так.

Ідея цього полягає в тому, що ви не закінчите перезаписати зміни, про які ваша програма не знала, що сталося - це в основному невеликий захід безпеки, який кидає .NET у всіх ваших оновленнях.

Якщо це узгоджено, шанси трапляються у вашій власній логіці (EG: Ви насправді оновлюєте дані самостійно в іншому способі між вибору та оновленням), але це може бути просто умова гонки між двома програмами.


34
Це відбувається в середовищі для одного користувача (на моїй машині розробників), тому я не думаю, що це може бути перегоном. Я прив'язуюсь до управління власною сіткою з EntityDataSource, тому я не впевнений, що саме відбувається за лаштунками, але у мене немає додаткового власного коду, який модифікує таблиці. Чи є спосіб змінити цей параметр одночасності?
strongopinions

3
Я думаю, що ви можете на основі стовпців у вашій моделі сутності (Це у вікні властивостей), але річ у тому, що це просто заважатиме вам бачити помилку, і вона все одно нічого не оновить. Чи можете ви переглядати команди SQL, що переходять у вашу базу даних (EG: Profiler SQL Server для MSSQL)? Таким чином ви могли побачити, яке оновлення створено, і ви зможете зрозуміти, чому це оновлення не впливає на жодні рядки.
fyjham

9
Якщо у суб'єкта господарювання є властивість часової позначки, то переконайтеся, що вона зберігається у вашому представленні, і переконайтеся, що суб'єкт господарювання правильно заповнив позначку часу.
anIBMer

У мене був стовпчик часових позначок, і як тільки я звернувся до нього, EF6.1 працював як слід, дякую за підказку @anelBMer
JQII

3
Якщо ви використовуєте часові позначки, для об'єкта, який ви хочете видалити, потрібно встановити ПК і властивість RowVersion, щоб успішно оновити його! Я встановлював властивість rowVersion (timetamp), після того як я приєднав об'єкт до відповідного DbSet, тому він не працював. Хороша робота!
Легенди

394

Я наткнувся на це, і це було спричинено тим, що поле (ідентифікатор (ключ) особи) не було встановлено. Таким чином, коли контекст пішов на збереження даних, він не міг знайти ідентифікатор = 0. Не забудьте поставити точку перерви у вашій заяві оновлення та переконатися, що ідентифікатор організації встановлено.

З коментаря Пола Беллори

У мене виникла точна проблема, викликана тим, що я забув включити прихований вхід ID на сторінку редагування .cshtml


3
+1 У мене була така ж проблема, і це допомогло знайти рішення. Виявляється, у моїй порядку замовлення було [Bind (Exclude = "OrderID")], що спричиняло значення ідентифікатора організації на HttpPost.
Dhaust

2
Саме цього я бракував. Ідентифікатор мого об’єкта був 0.
Ажар Хорасани

4
@ Html.HiddenFor (model => model.productID) - працював ідеально. Мені не вистачало продуктуID на сторінці редагування (MVC RAZOR)
Ravi Ram

2
У мене було подібне питання, але з поворотом. Для мене проблемою було те, що у мене не було правильно налаштовано таблицю sql. У моєму полі основного ключа не було встановлено значення автоматичного збільшення. Тож EF надішле запис, який я намагався вставити w / oa ключ, що добре, якщо ви пам'ятаєте сказати sql, що поле є полем автоматичного збільшення ідентичності, яке я забув: <
Agile Noob

1
Те саме питання, але з використанням складеного ключа. Одне з ключових значень не було встановлено.
obaylis

113

Ого, багато відповідей, але я помилився, коли зробив щось трохи інше, про що ніхто з інших не згадував.

Коротше кажучи, якщо ви створите новий об’єкт і скажете EF, що його модифікували за допомогою EntityState.Modifiedтоді, він викине цю помилку, оскільки вона ще не існує в базі даних. Ось мій код:

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

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

Так, це здається непростим, але воно виникло тому, що розглянутий метод раніше fooперейшов до нього, був створений раніше, тепер він лише someValueперейшов до нього і створює fooсам.

Легко виправити, просто змінити EntityState.Modifiedдо EntityState.Addedабо змінити , що вся лінія:

context.MyObject.Add(foo);

Дякуємо, що опублікували це. Це теж була моя проблема. Я скопіював якийсь код, який встановлював стан EntityState.Modified.
clayRay

23

Я зіткнувся з цією ж страшною помилкою ... :) Тоді я зрозумів, що забуваю встановити а

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

для первинного ключа об'єкта, що оновлюється! Я схильний забувати цю просту, але дуже важливу річ!

До речі: HiddenForдля ASP.NET MVC.


3
Це здається недоліком безпеки, щоб зберігати UserIdформу, дуже схильну до хакерів ... це слід заповнити згодом зHttpContext.Current.User.Identity.Name
Serj Sagan

@SerjSagan ви маєте рацію ... але поки ви зробите кілька перевірок на стороні сервера, щоб підтвердити UserId та поточне UserName, вам добре йти.
Леніел Маккаферрі

1
Моя думка, чому навіть зберігайте те, що HiddenForвам потрібно буде отримати його з HttpContextбудь-якого разу ... Я б взагалі не ставлю цю властивість у форму, що змусить мене завжди заселяти її стороною сервера ...
Serj Sagan

16

Перевірте, чи забули ви атрибут "DataKeyNames" в GridView. це обов'язково під час зміни даних у GridView

http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.datakeynames.aspx


+1. Ідеальне і просте рішення для мене. Я прив'язую GridView до EntityDataSource і не встановлював це своїм основним ключем на об'єкті.
Андез

Ми знаємо, що інтерфейс Kendo не підтримує складений ключ, але у випадку, якщо я додав новий стовпець, який конкретизував мої клавіші до одного, що відбувається тоді?
Бранислав

15

Проблема викликана однією з двох речей:

  1. Ви намагалися оновити рядок з однією або кількома властивостями Concurrency Mode: Fixed.., і оптимістична паралельність не дозволила зберегти дані. Тобто деякі змінили дані про рядки між часом отримання серверних даних та збереженням даних сервера.
  2. Ви намагалися оновити або видалити рядок, але рядок не існує. Ще один приклад того, що хтось змінює дані (у цьому випадку видаляє) між вилученням, а потім збережіть АБО ви не намагаєтесь оновити поле, яке не є ідентичністю (тобто StoreGeneratedPattern = Computed), і цього рядка не існує.

1
Це також може бути викликано, якщо всі властивості об'єкта, яким було призначено, їм присвоювали ті самі значення, що і раніше.
Serj Sagan

+1 для другого. У мене був StoreGeneratedPattern = Немає, зміна на StoreGeneratedPattern = Ідентифікація вирішила проблему. Дякую
tkt986

12

Я отримав цю саму помилку, оскільки частина ПК була стовпчиком дати, а запис, що вставляється, використовував DateTime.Now як значення для цього стовпця. Entity Framework буде вставляти значення з мілісекундною точністю, а потім шукати значення, яке воно щойно вставило, також з мілісекундною точністю. Однак SqlServer округлив значення до другої точності, і, таким чином, структура суті не змогла знайти значення точності в мілісекундах.

Рішенням було зрізати мілісекунди від DateTime.Now перед тим, як вставити.


2
У нас була така ж проблема, за винятком того, що ми вставляли в Dateстовпчик зі DateTimeзначенням
adam0101

1
Те ж саме. У нас був запис сховища даних і використовували часову позначку як частину ключа. Мітка часу в сховищі даних була SQL DateTime, але часова марка в C # не збігалася. Я змінив тип даних SQL на DateTime2 (7), оновив модель EF, і все було виправлено.
mmcfly

Зміна стовпця на Datetime2 (7) працювала і для мене. Спасибі @mmcfly
Dzejms

10

У мене була така ж проблема і @ webtrifusion в відповідь допомогли знайти рішення.

Моя модель використовувала Bind(Exclude)атрибут для ідентифікатора юридичної особи, який зумовлював значення HDpPost для ідентифікатора сутності.

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; }
    }
}   

Аналогічна проблема, з міркувань безпеки, у мене є Bind (включати = деякі поля). Ідентифікатора не було в списку. Також я додав його як прихований вхід. Потрібно стерти щось, що генерується MVC, або ідентифікатор взагалі не був. Дякую за допомогу.
MusicAndCode

10

У мене була така ж проблема, я вважаю, що це було викликано RowVersion, який був нульовим. Перевірте, чи ваш Id та RowVersion не є нульовими .

Для отримання додаткової інформації зверніться до цього посібника

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


Версія рядка в моєму випадку була недійсною
Пракаш

У моєму випадку я випадково видалив поле Id у своєму [Bind (Include = властивості)]. Додайте його назад, і він працював чудово.
Каверман

8

Я почав отримувати цю помилку, змінившись з моделі на першу. У мене є кілька потоків, що оновлюють базу даних, де деякі можуть оновлювати один і той же рядок. Я не знаю, чому у мене не виникло проблем із використанням моделі спочатку, припустимо, що вона використовує інший параметр за умовчанням.

Щоб обробляти його в одному місці, знаючи умови, при яких це може виникнути, я додав наступне перевантаження до мого класу DbContext:

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

Тоді телефонують, SaveChanges(true)де це можливо.


1
Гаразд, всі інші скаржаться на проблему, показуючи, як вони можуть її викликати і т. Д., Але ця відповідь має класну відповідь. Я використовую модель продовження оновлення (тут немає кнопки збереження, дитина), і отримував це в оновленнях сітки, коли поток EF відставав, і вирішив це. Блискуча робота, моє добре ім’я .. ти зробив мене схожим на героя - стоячи на плечі гігантів !!
Тоні Трембат-Дрейк

Допоміг і мені, подивіться на це, щоб дізнатися більше варіантів- stackoverflow.com/a/13891724/4836581
Zvi

7

Вам потрібно чітко включити BoundField первинного ключа. Якщо ви не хочете, щоб користувач бачив первинний ключ, його потрібно приховати через css:

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

Де "прихований" - це клас css, у якого його дисплей встановлений на "немає".


1
га, ти втягнув мене в той факт, що я видалив моє приховане поле id в ASP.NET MVC. Дякую @Paulo! :)
Томаш Іньевич

7

Під час редагування включайте ідентифікатор або первинний ключ об'єкта як приховане поле у ​​представленні

тобто

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

що вирішує проблему.

Крім того, якщо ваша модель включає невживаний предмет, включіть це теж і опублікуйте його на контролері


7

Я також натрапив на цю помилку. Проблема, яка виявилася, була викликана тригером на столі, який я намагався зберегти. Тригер використовував "INSTEAD OF INSERT", що означає 0 рядків, коли-небудь вставлених до цієї таблиці, отже, помилка. На щастя, можливо, функція тригера була неправильною, але я думаю, це може бути дійсною операцією, яка якось повинна оброблятися в коді. Сподіваюся, це допоможе комусь одного дня.


2
Суб'єкт може бути хитромудрий вважати, що рядки додані шляхом повернення оператора SELECT (зі стовпцем первинного ключа) з тригера.
jahu

1
Щоб розширити коментар від @jahu, мені довелося отримати фактичний ідентифікатор щойно вставленого елемента, який потрібно повернути з мого тригера, а назва стовпця має відповідати стовпцю ідентифікаційної таблиці тригера (у моєму випадку насправді перегляду, щоб він не став Я не маю власної ідентичності, але я підманув Edmx вважати, що це робиться). Мій тригер робив вставку в окрему таблицю, тому я щойно додав цей останній рядок до мого тригера:SELECT SCOPE_IDENTITY() as MyViewId
DannyMeister

Дивіться також питання: stackoverflow.com/questions/5820992 / ...
J. Польфер

У моєму випадку я робив операцію з видалення об'єктів у дочірній колекції, але був видалений тригер для видалення для однієї з дочірніх сутностей, що призвело до видалення іншого з дочірніх об'єктів. Це спричинило помилку, оскільки N - 1 рядків було порушено через тригер, який видаляв одне з дочірніх сутностей, перш ніж фреймворк сутності намагався його видалити.
скелет

6

Я зіткнувся з цим питанням на таблиці, у якій відсутній первинний ключ, і в ньому був стовпець DATETIME (2, 3) (тому "первинний ключ" об'єкта був комбінацією всіх стовпців) ... Під час виконання вставки часова мітка мала точніший час (2018-03-20 08: 29: 51.8319154), який був усічений до (2018-03-20 08: 29: 51.832), тому пошук на ключових полях не вдається.


5

У мене теж була ця помилка. Є деякі ситуації, коли Організація може не знати про фактичний контекст бази даних, який ви використовуєте, або Модель може бути іншою. Для цього встановіть: EntityState.Modified; до EntityState.Added;

Зробити це:

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

Це забезпечить, що суб'єкт господарювання знає, що ви використовуєте або додаєте державу, з якою працюєте. На цьому етапі потрібно встановити всі правильні Модельні значення. Обережно не втрачайте жодних змін, які могли бути внесені на задній план.

Сподіваюсь, це допомагає.


1
ти гуру! це працює для мене!
Ернальдо Гонсалес

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

Мій rowversion був недійсним, тому довелося додати це до подання, яке вирішило мою проблему


Не передавав RowVersion від Погляду до дії редагування, плюс я забув зробити прив'язку моделі для RowVersion. У той час, коли ви зберігаєте об'єкт в db, вам потрібно попереднє значення RowVersion подати в db разом з об'єктом для перевірки сумісності. Ви робите нерозумні помилки, коли вам потрібні речі швидше!
Dhanuka777

5

Лінія [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.None)]зробила трюк у моєму випадку:

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


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

4

Просто переконайтесь, що в таблиці та формі оновлено первинний ключ та edmx.

Я виявив, що помилки під час оновлення зазвичай були через: - Немає первинного ключа в таблиці - Немає первинного ключа в редагуванні подання / форми (наприклад @Html.HiddenFor(m=>m.Id)


4

У мене була така ж проблема. У моєму випадку я намагався оновити первинний ключ, що заборонено.


4

Я отримав цю помилку спорадично під час використання asyncметоду. Не сталося з того часу, як я перейшов на синхронний метод.

Помилки спорадично:

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

Працює весь час:

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

Хоча це і вирішило мою проблему, вона служила для вказування на основну проблему, згадану раніше в цій публікації про версії ПК та рядків. Я нехтував додаванням карти схеми для нової таблиці, що ще більше ускладнилося тим, що ПК не дотримувався правила конвенції про іменування. <Ім'я таблиці> Ідентифікатор
midohioboarder

3

Я отримав цю помилку під час видалення деяких рядків у БД (у циклі) та додавання нових у цій же таблиці.

Для мене рішення полягало в тому, щоб динамічно створити новий контекст у кожній ітерації циклу


Мені довелося зробити те саме, все ще не впевнений, чому в першу чергу виникла проблема, але це працює.
Джед Грант

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

Чи можете ви пояснити, на що тут йдеться "це", а що таке ObjectStateManager? Я намагаюся це зробити в нашому базовому класі сховищ, але отримую помилки
Наомі

3

Це також станеться, якщо ви намагаєтеся вставити в унікальну ситуацію з обмеженнями, тобто якщо у вас є лише один тип адреси на роботодавця, і ви намагаєтесь вставити другий того ж типу з тим же роботодавцем, ви отримаєте ту ж проблему .

АБО

Це також може статися, якщо всі властивості об'єкта, яким було призначено, їм присвоювали ті самі значення, що і раніше.

        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

Якщо ви намагаєтеся створити відображення у файлі edmx до функції "Імпорт", це може призвести до цієї помилки. Просто очистіть поля для вставки, оновлення та видалення, які знаходяться у розділі "Деталі картографування" для даної сутності у вашому edmx, і це повинно працювати. Я сподіваюся, що я зрозумів це.


2

Я отримав це виняток, коли приєднав об’єкт, який не існував у базі даних. Я припускав, що об’єкт завантажений з окремого контексту, але якщо це був перший раз, коли користувач відвідував сайт, об’єкт створювався з нуля. У нас є автоматичні збільшення первинних ключів, тому я міг би замінити

context.Users.Attach(orderer);

з

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

2

Ну, у мене це ж питання. Але це було через мою власну помилку. Насправді я економив об’єкт, а не додавав його. Отже, це був конфлікт.


2

Один із способів налагодити цю проблему в середовищі сервера Sql - це використовувати Профілер Sql, що додається до вашої копії SqlServer, або якщо за допомогою версії Express отримати копію Express Profiler безкоштовно від CodePlex, перейшовши за наступним посиланням:

Експрес-Профілер

За допомогою Sql Profiler ви можете отримати доступ до того, що надсилається EF до БД. У моєму випадку це становило:

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

Я скопіював це вставлене у вікно запиту на сервері Sql і виконав його. Звичайно, хоч і працював, цей запит вплинув на 0 записів, отже, помилка повертається EF.

У моєму випадку проблема була викликана CategoryID.

Не було ідентифіковано CategoryID за допомогою ID EF, що надсилається до бази даних, отже, 0 записів впливають.

Не в цьому помилка EF, а навпаки, баггі-нуль, що поєднує "??" заява в Контролері перегляду, який надсилав дурниці вниз до рівня даних.


2

Жодна з вищезазначених відповідей не охоплювала моєї ситуації та її вирішення.

Код, де помилка була кинута в контролер MVC5:

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

Я отримав цей виняток, коли я зберігав об'єкт у поданні Правка. Причина, яку він кинув, це тому, що, коли я повернувся, щоб зберегти його, я змінив властивості, які формували первинний ключ на об'єкті. Таким чином, встановлення свого стану на Modified не мало сенсу для EF - це був новий запис, а не раніше збережений.

Вирішити це можна за допомогою A) змінивши виклик збереження на Додати об’єкт або B) просто не змінюйте первинний ключ під час редагування. Я зробив Б).


2

Коли в прийнятій відповіді сказано, що " не закінчиться перезапис змін, про які ваша програма не знала, що сталося ", я був скептичний, оскільки мій об'єкт був нещодавно створений. Але потім, виявляється, з’явивсяINSTEAD OF UPDATE, INSERT- TRIGGER до таблиці який оновлював обчислений стовпчик тієї ж таблиці.

Як тільки я змінив це AFTER INSERT, UPDATE, він працював чудово.


2

Це сталося зі мною через невідповідність між датою та датою2. Як не дивно, він добре працював до того, як тестер виявив проблему. Моя модель First Code включала DateTime як частину первинного ключа:

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

Створений стовпець - це стовпець дати. Викликаючи SaveChanges, EF генерував такий SQL:

-- 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))

Оскільки він намагався співставити стовпець datetime зі значенням datetime2, це не дало результатів. Єдине рішення, про яке я міг придумати, - це змінити стовпчик на datetime2:

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

1
Незвичайність його роботу vs. не працює має справу з лежачим в основі формату базі / datetimeVS. datetime2. По суті деякі значення мілісекунди оцінюються на відповідність, інші - не. Зі мною трапилось те саме, і я теж перейшов DateTime2.
xr280xr

+1 Я хотів би, щоб я міг +100 на цьому для вас. Після перегляду багатьох місць я нарешті знайшов це і зрозумів, що, дійсно, у мене був Datetime як частина мого основного ключа. Так, це справді це виправило. Я оновив стовпчик до Datetime2, і він працював. Тепер моя яловичина має Entity Framework для розробки такого хитрого запиту для цього, який змушує мене це робити.
Catchops
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.