System.Data.Linq.ChangeConflictException : 행이 없거나 변경되었습니다.
LINQ (LINQDataSource 없음)를 사용하여 선택한 gridview 행을 삭제하려고합니다.
선택이 변경되면 detailsview 바인딩도 변경됩니다. 데이터베이스에 새 항목을 추가 할 수 있지만이 코드를 updatePanel 내부의 삭제 버튼에 추가했을 때 예외가 발생했습니다.
try
{
var query = from i in db.QuestionModules
where i.QuestionModuleID == QuestionModuleID
select i;
QuestionModule o = query.First();
db.QuestionModules.DeleteOnSubmit(o);
db.SubmitChanges();
}
이것은 내가 얻는 예외입니다.
System.Data.Linq.ChangeConflictException: Row not found or changed. at
System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode
failureMode) at
System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode)
at System.Data.Linq.DataContext.SubmitChanges()
약 일주일 동안이 문제가 있었는데 내가 무엇을하든 여전히 존재하며 레코드가 삭제되지 않습니다.
무엇을 해야할지에 대한 아이디어가 있습니까?
OK-(적어도 내 경우에는) 대답은 DBML 파일에서 기본 키가 아닌 열의 UpdateCheck 속성을 Never 로 설정 하는 것이 었습니다 . 이렇게하면 "행을 찾을 수 없거나 변경되지 않음"문제가 즉시 해결되었습니다.
Microsoft가 Entity Framework에 찬성하여 Linq-To-Sql을 사용하고 있다는 소문을 감안할 때 이러한 종류의 버그가 수정 될지 궁금합니다.
필드 중 하나가 Linq To SQL 디자이너와 실제 데이터베이스에서 다른 내용이 있기 때문에이 오류가 발생할 수 있습니다.
제 경우에는 필드 중 하나가 데이터베이스에서 nullable이고 디자이너에서는 nullable이 아니기 때문에 디자이너에서 nullable로 만들면서 문제가 즉시 해결되었습니다.
나는 똑같은 문제를 겪고 있으며이 블로그 를 보았습니다. 기본적으로 Linq-To-Sql이 낙관적 동시성에 문제가 있음을 설명합니다.
- 고정밀 날짜 시간 필드가 사용됩니다. 해결책은 UpdateCheck를 DBML 파일에 대해 절대로 설정하지 않는 것입니다.
- 보이지 않는 것으로 설정된 GridView 열이 데이터 개체의 속성에 액세스하고 있습니다 (이 두 번째 이유는 의미가 없지만 해당 블로그에서 모든 분노를 불러 일으 킵니다).
아직 이러한 솔루션을 시도하지 않았지만 일단 여기에 다시 게시 할 것입니다.
업데이트하기 직전에 개체를 새로 고쳐서이 문제를 해결했습니다. KeepChanges 옵션으로이 작업을 수행합니다.
db.Refresh(System.Data.Linq.RefreshMode.KeepChanges, employee);
문제는 단순히 테이블의 DBML 정의가 데이터베이스 정의의 상태와 일치하지 않는다는 것입니다. 방금 DBML 모델을 제거하고 데이터베이스에서 다시 삽입하면 작동했습니다.
이것이 누군가에게 도움이되기를 바랍니다.
내 상황에서도 일하는 것 같았다. 나는 다른 테이블의 행에 대한 여러 외래 키 관계가있는 행을 제출 한 적이없는 메모리 내부를 구축하고있었습니다. InsertOnSubmit이 작동하는 것처럼 보였지만 후속 DeleteOnSubmit에서 해당 행을 찾을 수 없음 오류가 발생했습니다. 제출 한 행의 모든 필드를 채우지 않았으므로 그와 관련이 있는지는 모르겠지만 기본 테이블의 기본 키가 아닌 모든 열을 표시하면 오류 메시지가 제거되었습니다.
한 가지 더 생각 : 열의 UpdateCheck 정책을 'Never'로 표시하면 낙관적 동시성 검사의 기반으로 사용되지 않는다는 의미입니다. 이는 두 명의 사용자가 해당 열의 다른 데이터로 주어진 행을 덮어 쓸 수 있으며 충돌이 감지되지 않음을 의미합니다. 즉, 행을 제출 한 마지막 사용자가 이전 사용자 제출의 값을 덮어 쓰게됩니다. 나는 여러 온라인 독서에서 이것에 대한 한 가지 부분적인 해결책이 제출 직전에 Refresh 메서드를 사용하여 변경 사항을 동기화하는 것이라고 수집했습니다. 물론 행에 대한 비관적 잠금이 없으면 새로 고침과 제출 사이에 행이 변경되지 않는다는 보장은 없지만 대규모 데이터베이스와 관련된 대부분의 시나리오에서 이는 드뭅니다.
업데이트 : 추가 검토에서 다른 사람에게 영향을 미칠 수있는 시나리오를 발견 한 것 같아 만일을 대비하여 공유 할 것이라고 생각했습니다. SQL LINQ에서 발생한 문제 중 적어도 일부는 트리거와 관련이 있습니다. SQL LINQ를 사용하여 행을 제출하고 DBA에 해당 행의 일부 열에 정보를 쓰도록 설계된 트리거가있는 경우 SQL LINQ 모델은 기본적으로 '항상'행이 마지막 쓰기 이후 변경된 것으로 판단합니다. . 부분적으로 채워진 행을 제출하고 DBA의 트리거가 일부 열을 채우고 있으므로 코드에서 행을 추가로 수정하려고 할 때 트리거에 의해 채워진 열을 기반으로 변경 충돌을 감지했습니다. 나는 이것을 처리하는 가장 좋은 방법을 조사하고 있지만 이러한 트리거가 채워진 필드를 '변경된 경우'또는 '사용 안 함'의 UpdateCheck 정책을 사용하도록 변경하는 중입니다. 도움이되기를 바랍니다.
이는 열 정의가 일치하지 않는 경우입니다. 표를 제거 .dbml
하고 다시 추가하십시오. auto generate value property = true
기본 키 또는 날짜 / 시간 열과 같이 자동 생성 된 데이터가있는 열에 대해 변경해야합니다 .
행을 업데이트 할 때 유사한 changeconflictexception / "행을 찾을 수 없거나 변경됨"이 발생했습니다. dbml에 탭을 다시 추가하여 문제를 해결했습니다.
null
관련 테이블 (즉, 업데이트 할 테이블)에 값이 포함 된 열이 없는지 확인합니다 .
내가 가진 문제는 .net 프레임 워크에 DateTime 유형이 있지만 우리의 데이터베이스 필드는 더 높은 정밀도 데이터 유형 인 DateTime2 유형이었습니다. 그래서 우리가 변경 사항을 제출할 때 객체의 날짜 필드와 DB는 불과 몇 나노초 떨어져서 동시성 오류가 발생했습니다. 이는 최신 MSSQL 버전으로 마이그레이션하고 DateTime 필드를 DateTime2로 변환했을 때 발생했습니다.
그래서 우리가 가진 코드에서 :
Obj.DateUpdated = DateTime.Now()
우리는 그것을 다음과 같이 변경했습니다.
Obj.DateUpdated = DateTime.Parse(DateTime.Now.ToString())
따라서 업그레이드 및 / 또는 마이그레이션 후이 오류가 발생하면 데이터 유형, 특히 날짜 필드를 확인하십시오.
업데이트 패널 포스트 백 중에 gridview 및 datasource에서 databind ()를 실행하여이 문제를 해결할 수있었습니다.
protected void UpdatePanel1_Load(object sender, EventArgs e)
{
GridView1.DataBind();
LinqDataSource1.DataBind();
}
선택 색인이 변경 될 때마다 업데이트 패널을 새로 고치고 충돌을 해결할 수있었습니다.
도움이 되었기를 바랍니다.
아래에:
QuestionModule o = query.First();
다음 명령을 추가해야합니다.
db.QuestionModule.Attach(o);
Also - if you're calling the selecting method for the linqdatasource and setting e.result manually, make sure you're including any foreignkey values as well.
Nothing else worked for me but this.
I just wanted to add my scenario for anybody who may have this issue.
We use a custom T4 against our Linq to SQL dbml. We basically just modified the original get/set of string properties to automatically trim and set null.
get { return _OfficiantNameMiddle.GetValueOrNull(); }
set
{
value = value.GetValueOrNull();
if (_OfficiantNameMiddle != value)
{
_IsDirty = true;
OnOfficiantNameMiddleChanging(value);
SendPropertyChanging("OfficiantNameMiddle");
_OfficiantNameMiddle = value;
SendPropertyChanged("OfficiantNameMiddle");
OnOfficiantNameMiddleChanged();
}
}
Legacy data in our database had some leading/trailing spaces so any concurrency check on these columns failed to result in a match (it was comparing the trimmed value against the non-trimmed database value). It was really easy to profile SQL, grab the SQL and start commenting out the items in the WHERE clause until it started returning a row during the concurrency check.
Luckily, we have a LastUpdatedOn field in our tables that is automatically set via OnValidate(System.Data.Linq.ChangeAction).
partial void OnValidate(System.Data.Linq.ChangeAction action)
{
if (action == System.Data.Linq.ChangeAction.Insert)
{
CreatedBy = CurrentUserID;
CreatedOn = DateTime.Now;
LastUpdatedBy = CreatedBy;
LastUpdatedOn = CreatedOn;
}
else if (action == System.Data.Linq.ChangeAction.Update)
{
LastUpdatedBy = CurrentUserID;
LastUpdatedOn = DateTime.Now;
}
}
In order to bypass the problem, we just set the concurrency check to Never on all columns except the Primary Key columns and LastUpdatedOn column. This worked for us.
I had a similar problem and although deleting and re-adding the DBML table/class helped some users, for me it was a bit different since I'm using WCF with detached entity and a ListView on the client.
If I used the .Attach(entity) it failed - "Row not found or changed" But when using .Attach(entity, original) it works every time
public void DeleteTask(Task task)
{
TwoDooDataContext db = new TwoDooDataContext();
db.Tasks.Attach(task,GetTaskByID(task.ID));
db.Tasks.DeleteOnSubmit(task);
db.SubmitChanges();
}
For me it was an enum column (mapped to a varchar) which caused the problem, so I had to pass update check to never.
The way i fixed it was: First I update the database, then I set the new values for the grid as
e.Keys["ColumnOne"] ="new value"
e.Keys["ColumnTwo"] ="new value"
All this was done under the GridView_RowUpdating
event.
As @dherrin79 indicated, this can be caused because of a precision variance between the database and the code. For me, the issue was the database column was supposed to be decimal(10,2), but it had been created as decimal(18,0). This was for a money field, so perhaps I should have used the money column type.
So, I saved a dollar amount, like $3.14 to it, but the decimal was stripped. This resulted in the database value being changed and not matching the value in C#.
Hope this helps.
For us the problem started when we switched to DateTime2 on the SQL Server side. Just marking fields with Column(DbType = "DateTime2") did not help. So, what happened was that initially on the database side we declared our columns as DateTime2(3) to be "backward compatible" with the old DateTime type and everything seemed to work fine until we noticed that when we use SQL-2-Linq we get the "Row not found or changed" exception in the updates of those date fields. To make the quite-long story short the solution was to do 2 things:
- Mark the columns with [Column(DbType = "DateTime2(3)", CanBeNull = false)] to match the database declaration. AND
- Trim the extra precision digits from the properties in setters like so:
[Column(DbType = "DateTime2(3)", CanBeNull = false)] public DateTime ModifiedAt { get => _modifiedAt; set => _modifiedAt = value.AddTicks(-(value.Ticks % TimeSpan.TicksPerMillisecond)); }
'IT Share you' 카테고리의 다른 글
가시성 : 숨김 및 표시 간의 성능 차이 : 없음 (0) | 2020.12.02 |
---|---|
iOS 11 navigationItem.titleView 너비가 설정되지 않음 (0) | 2020.12.02 |
jquery / javascript로 숫자 나 문자를 감지합니까? (0) | 2020.12.02 |
iOS 기기에서 PHP 페이지에 액세스했는지 확인 (0) | 2020.12.02 |
iOS 7 (4 인치 레티 나 디스플레이)에서 앱을 실행할 때 검은 색 막대가 표시됨 (0) | 2020.12.02 |