Apparent race condition/concurrency issue
I have a web application written using ASP.NET MVC (C#), Entity Framework and an Oracle database. In one of the controllers I have code similar to the following (stripped down to show only what I consider necesary for this question):
using (var context = CreateContext())
{
//Other code ...
var workItem = //Get work item from context
var nextReviewers =
await context.WorkItemReviewers
.Where(r => r.WorkItemId == workItem.Id)
.Where(r => r.Position > workItem.NextReviewerPosition)
.OrderBy(r => r.Position)
.ToArrayAsync();
if (nextReviewers.Count() > 0)
{
workItem.Status = "A";
workItem.StatusDetails = "A";
workItem.NextReviewerPosition = nextReviewers.First().Position;
//Other Code
}
else
{
workItem.Status = "B";
workItem.StatusDetails = "B";
workItem.NextReviewerPosition = null;
}
//Other Code
await context.SaveChangesAsync();
}
Based on the code above, I never expect the values of Status or StatusDetails to ever be different but I have a situation in production where two requests came in about 3-4 milliseconds apart and now, inexplicably, I have the following values in the database: Status = "B"; StatusDetails = "A".
Am I missing something? Is there a logical explanation for this based on how EntityFramework (against Oracle 11g) might behave in ASP.NET?
asp.net-mvc entity-framework
add a comment |
I have a web application written using ASP.NET MVC (C#), Entity Framework and an Oracle database. In one of the controllers I have code similar to the following (stripped down to show only what I consider necesary for this question):
using (var context = CreateContext())
{
//Other code ...
var workItem = //Get work item from context
var nextReviewers =
await context.WorkItemReviewers
.Where(r => r.WorkItemId == workItem.Id)
.Where(r => r.Position > workItem.NextReviewerPosition)
.OrderBy(r => r.Position)
.ToArrayAsync();
if (nextReviewers.Count() > 0)
{
workItem.Status = "A";
workItem.StatusDetails = "A";
workItem.NextReviewerPosition = nextReviewers.First().Position;
//Other Code
}
else
{
workItem.Status = "B";
workItem.StatusDetails = "B";
workItem.NextReviewerPosition = null;
}
//Other Code
await context.SaveChangesAsync();
}
Based on the code above, I never expect the values of Status or StatusDetails to ever be different but I have a situation in production where two requests came in about 3-4 milliseconds apart and now, inexplicably, I have the following values in the database: Status = "B"; StatusDetails = "A".
Am I missing something? Is there a logical explanation for this based on how EntityFramework (against Oracle 11g) might behave in ASP.NET?
asp.net-mvc entity-framework
You have omitted too much I think. What isworkItem
? How is it tracked and set? Is it a new entity instance or a retrieved one? Why is it relevant? If it is retrieved & tracked and the Status is set to the same value (ie. its "A" and you set it to "A" again) then it is ignored when you update it as it is not considered modified (by default). So that could result in a race condition.
– Igor
Jan 3 at 17:17
BTW - I recommend you use unique constraints to avoid duble entries and use a versioning column likerowversion
in sql server (I am not 100% sure how that translates into oracle but I assume there is a similar type). The later prevents race conditions and the first committing change wins, the later commit will receive an Exception which you can then handle.
– Igor
Jan 3 at 17:21
In your code, are Status and StatusDetails both string types/primitive types, or are they references to other entities? Where is workItem declared, because I don't see from your example that it is associated to the context. I understand that it may seem prudent to obfuscate your actual code to hide proprietary details or attempt to simplify the issue, but this often leaves out key details that may explain your issue and leave people guessing at false positives that don't impact the real code.
– Steve Py
Jan 3 at 21:50
@Igor, I've edited slightly to show that work item is retrieved from the context.
– Tolu
Jan 4 at 22:25
@Steve Py, Status and Status details are strings.
– Tolu
Jan 4 at 22:25
add a comment |
I have a web application written using ASP.NET MVC (C#), Entity Framework and an Oracle database. In one of the controllers I have code similar to the following (stripped down to show only what I consider necesary for this question):
using (var context = CreateContext())
{
//Other code ...
var workItem = //Get work item from context
var nextReviewers =
await context.WorkItemReviewers
.Where(r => r.WorkItemId == workItem.Id)
.Where(r => r.Position > workItem.NextReviewerPosition)
.OrderBy(r => r.Position)
.ToArrayAsync();
if (nextReviewers.Count() > 0)
{
workItem.Status = "A";
workItem.StatusDetails = "A";
workItem.NextReviewerPosition = nextReviewers.First().Position;
//Other Code
}
else
{
workItem.Status = "B";
workItem.StatusDetails = "B";
workItem.NextReviewerPosition = null;
}
//Other Code
await context.SaveChangesAsync();
}
Based on the code above, I never expect the values of Status or StatusDetails to ever be different but I have a situation in production where two requests came in about 3-4 milliseconds apart and now, inexplicably, I have the following values in the database: Status = "B"; StatusDetails = "A".
Am I missing something? Is there a logical explanation for this based on how EntityFramework (against Oracle 11g) might behave in ASP.NET?
asp.net-mvc entity-framework
I have a web application written using ASP.NET MVC (C#), Entity Framework and an Oracle database. In one of the controllers I have code similar to the following (stripped down to show only what I consider necesary for this question):
using (var context = CreateContext())
{
//Other code ...
var workItem = //Get work item from context
var nextReviewers =
await context.WorkItemReviewers
.Where(r => r.WorkItemId == workItem.Id)
.Where(r => r.Position > workItem.NextReviewerPosition)
.OrderBy(r => r.Position)
.ToArrayAsync();
if (nextReviewers.Count() > 0)
{
workItem.Status = "A";
workItem.StatusDetails = "A";
workItem.NextReviewerPosition = nextReviewers.First().Position;
//Other Code
}
else
{
workItem.Status = "B";
workItem.StatusDetails = "B";
workItem.NextReviewerPosition = null;
}
//Other Code
await context.SaveChangesAsync();
}
Based on the code above, I never expect the values of Status or StatusDetails to ever be different but I have a situation in production where two requests came in about 3-4 milliseconds apart and now, inexplicably, I have the following values in the database: Status = "B"; StatusDetails = "A".
Am I missing something? Is there a logical explanation for this based on how EntityFramework (against Oracle 11g) might behave in ASP.NET?
asp.net-mvc entity-framework
asp.net-mvc entity-framework
edited Jan 4 at 22:32
Erik Philips
41.5k694126
41.5k694126
asked Jan 3 at 13:36
ToluTolu
465416
465416
You have omitted too much I think. What isworkItem
? How is it tracked and set? Is it a new entity instance or a retrieved one? Why is it relevant? If it is retrieved & tracked and the Status is set to the same value (ie. its "A" and you set it to "A" again) then it is ignored when you update it as it is not considered modified (by default). So that could result in a race condition.
– Igor
Jan 3 at 17:17
BTW - I recommend you use unique constraints to avoid duble entries and use a versioning column likerowversion
in sql server (I am not 100% sure how that translates into oracle but I assume there is a similar type). The later prevents race conditions and the first committing change wins, the later commit will receive an Exception which you can then handle.
– Igor
Jan 3 at 17:21
In your code, are Status and StatusDetails both string types/primitive types, or are they references to other entities? Where is workItem declared, because I don't see from your example that it is associated to the context. I understand that it may seem prudent to obfuscate your actual code to hide proprietary details or attempt to simplify the issue, but this often leaves out key details that may explain your issue and leave people guessing at false positives that don't impact the real code.
– Steve Py
Jan 3 at 21:50
@Igor, I've edited slightly to show that work item is retrieved from the context.
– Tolu
Jan 4 at 22:25
@Steve Py, Status and Status details are strings.
– Tolu
Jan 4 at 22:25
add a comment |
You have omitted too much I think. What isworkItem
? How is it tracked and set? Is it a new entity instance or a retrieved one? Why is it relevant? If it is retrieved & tracked and the Status is set to the same value (ie. its "A" and you set it to "A" again) then it is ignored when you update it as it is not considered modified (by default). So that could result in a race condition.
– Igor
Jan 3 at 17:17
BTW - I recommend you use unique constraints to avoid duble entries and use a versioning column likerowversion
in sql server (I am not 100% sure how that translates into oracle but I assume there is a similar type). The later prevents race conditions and the first committing change wins, the later commit will receive an Exception which you can then handle.
– Igor
Jan 3 at 17:21
In your code, are Status and StatusDetails both string types/primitive types, or are they references to other entities? Where is workItem declared, because I don't see from your example that it is associated to the context. I understand that it may seem prudent to obfuscate your actual code to hide proprietary details or attempt to simplify the issue, but this often leaves out key details that may explain your issue and leave people guessing at false positives that don't impact the real code.
– Steve Py
Jan 3 at 21:50
@Igor, I've edited slightly to show that work item is retrieved from the context.
– Tolu
Jan 4 at 22:25
@Steve Py, Status and Status details are strings.
– Tolu
Jan 4 at 22:25
You have omitted too much I think. What is
workItem
? How is it tracked and set? Is it a new entity instance or a retrieved one? Why is it relevant? If it is retrieved & tracked and the Status is set to the same value (ie. its "A" and you set it to "A" again) then it is ignored when you update it as it is not considered modified (by default). So that could result in a race condition.– Igor
Jan 3 at 17:17
You have omitted too much I think. What is
workItem
? How is it tracked and set? Is it a new entity instance or a retrieved one? Why is it relevant? If it is retrieved & tracked and the Status is set to the same value (ie. its "A" and you set it to "A" again) then it is ignored when you update it as it is not considered modified (by default). So that could result in a race condition.– Igor
Jan 3 at 17:17
BTW - I recommend you use unique constraints to avoid duble entries and use a versioning column like
rowversion
in sql server (I am not 100% sure how that translates into oracle but I assume there is a similar type). The later prevents race conditions and the first committing change wins, the later commit will receive an Exception which you can then handle.– Igor
Jan 3 at 17:21
BTW - I recommend you use unique constraints to avoid duble entries and use a versioning column like
rowversion
in sql server (I am not 100% sure how that translates into oracle but I assume there is a similar type). The later prevents race conditions and the first committing change wins, the later commit will receive an Exception which you can then handle.– Igor
Jan 3 at 17:21
In your code, are Status and StatusDetails both string types/primitive types, or are they references to other entities? Where is workItem declared, because I don't see from your example that it is associated to the context. I understand that it may seem prudent to obfuscate your actual code to hide proprietary details or attempt to simplify the issue, but this often leaves out key details that may explain your issue and leave people guessing at false positives that don't impact the real code.
– Steve Py
Jan 3 at 21:50
In your code, are Status and StatusDetails both string types/primitive types, or are they references to other entities? Where is workItem declared, because I don't see from your example that it is associated to the context. I understand that it may seem prudent to obfuscate your actual code to hide proprietary details or attempt to simplify the issue, but this often leaves out key details that may explain your issue and leave people guessing at false positives that don't impact the real code.
– Steve Py
Jan 3 at 21:50
@Igor, I've edited slightly to show that work item is retrieved from the context.
– Tolu
Jan 4 at 22:25
@Igor, I've edited slightly to show that work item is retrieved from the context.
– Tolu
Jan 4 at 22:25
@Steve Py, Status and Status details are strings.
– Tolu
Jan 4 at 22:25
@Steve Py, Status and Status details are strings.
– Tolu
Jan 4 at 22:25
add a comment |
1 Answer
1
active
oldest
votes
Based on the code above, given that the workItem entity updated was loaded within the scope of the DB context and that the 2 values are strings, I'd have to say with 99.5% certainty that this code is not responsible for the behaviour you are seeing. (though I will definitely be watching this item to see if that is proven wrong:) I would be taking a close look at everywhere that either Status or StatusDetails is being used in relation to the calls made to the service. I suspect some other code is unexpectedly changing one or the other and calling SaveChanges.
A small optimization I can suggest:
var nextReviewer = context.WorkItemReviewers
.Where(r => r.WorkItemId == workItem.Id
&& r.Position > workItem.NextReviewerPosition)
.OrderBy(r => r.Position)
.Select(r => new { r.Position }) // Add any other details you may need from reviewer and other related entities.
.FirstOrDefault();
if (nextReviewer != null)
{
workItem.Status = "A";
workItem.StatusDetails = "A";
workItem.NextReviewerPosition = nextReviewer.Position;
//Other Code
}
else
{
workItem.Status = "B";
workItem.StatusDetails = "B";
workItem.NextReviewerPosition = null;
}
By using .Select()
you can optimize the query to just return back the columns from the tables you need which will make calls to the DB faster. Unless the query is expected to be relatively heavy in terms of time (> ~500ms for instance) I'd also avoid the async operation. It's purpose is to make the server more responsive when dealing with bigger operations. Using it on everything will make all operations a wee bit slower than necessary. Once you've optimized the data coming back, then async can be considered if it still requires a bit of time to chew through.
Steve-py, thanks for this! My suspicion too is that the change is occurring elsewhere but I've not been able to pin it down. I'm up-voting this but I won't be accepting this as the answer just yet until I have full clarity. Thanks a bunch too for the suggestions on limiting the columns returned from the database and on async! I always thought async is at least just as fast and sometimes faster...
– Tolu
Jan 8 at 10:14
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54023369%2fapparent-race-condition-concurrency-issue%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Based on the code above, given that the workItem entity updated was loaded within the scope of the DB context and that the 2 values are strings, I'd have to say with 99.5% certainty that this code is not responsible for the behaviour you are seeing. (though I will definitely be watching this item to see if that is proven wrong:) I would be taking a close look at everywhere that either Status or StatusDetails is being used in relation to the calls made to the service. I suspect some other code is unexpectedly changing one or the other and calling SaveChanges.
A small optimization I can suggest:
var nextReviewer = context.WorkItemReviewers
.Where(r => r.WorkItemId == workItem.Id
&& r.Position > workItem.NextReviewerPosition)
.OrderBy(r => r.Position)
.Select(r => new { r.Position }) // Add any other details you may need from reviewer and other related entities.
.FirstOrDefault();
if (nextReviewer != null)
{
workItem.Status = "A";
workItem.StatusDetails = "A";
workItem.NextReviewerPosition = nextReviewer.Position;
//Other Code
}
else
{
workItem.Status = "B";
workItem.StatusDetails = "B";
workItem.NextReviewerPosition = null;
}
By using .Select()
you can optimize the query to just return back the columns from the tables you need which will make calls to the DB faster. Unless the query is expected to be relatively heavy in terms of time (> ~500ms for instance) I'd also avoid the async operation. It's purpose is to make the server more responsive when dealing with bigger operations. Using it on everything will make all operations a wee bit slower than necessary. Once you've optimized the data coming back, then async can be considered if it still requires a bit of time to chew through.
Steve-py, thanks for this! My suspicion too is that the change is occurring elsewhere but I've not been able to pin it down. I'm up-voting this but I won't be accepting this as the answer just yet until I have full clarity. Thanks a bunch too for the suggestions on limiting the columns returned from the database and on async! I always thought async is at least just as fast and sometimes faster...
– Tolu
Jan 8 at 10:14
add a comment |
Based on the code above, given that the workItem entity updated was loaded within the scope of the DB context and that the 2 values are strings, I'd have to say with 99.5% certainty that this code is not responsible for the behaviour you are seeing. (though I will definitely be watching this item to see if that is proven wrong:) I would be taking a close look at everywhere that either Status or StatusDetails is being used in relation to the calls made to the service. I suspect some other code is unexpectedly changing one or the other and calling SaveChanges.
A small optimization I can suggest:
var nextReviewer = context.WorkItemReviewers
.Where(r => r.WorkItemId == workItem.Id
&& r.Position > workItem.NextReviewerPosition)
.OrderBy(r => r.Position)
.Select(r => new { r.Position }) // Add any other details you may need from reviewer and other related entities.
.FirstOrDefault();
if (nextReviewer != null)
{
workItem.Status = "A";
workItem.StatusDetails = "A";
workItem.NextReviewerPosition = nextReviewer.Position;
//Other Code
}
else
{
workItem.Status = "B";
workItem.StatusDetails = "B";
workItem.NextReviewerPosition = null;
}
By using .Select()
you can optimize the query to just return back the columns from the tables you need which will make calls to the DB faster. Unless the query is expected to be relatively heavy in terms of time (> ~500ms for instance) I'd also avoid the async operation. It's purpose is to make the server more responsive when dealing with bigger operations. Using it on everything will make all operations a wee bit slower than necessary. Once you've optimized the data coming back, then async can be considered if it still requires a bit of time to chew through.
Steve-py, thanks for this! My suspicion too is that the change is occurring elsewhere but I've not been able to pin it down. I'm up-voting this but I won't be accepting this as the answer just yet until I have full clarity. Thanks a bunch too for the suggestions on limiting the columns returned from the database and on async! I always thought async is at least just as fast and sometimes faster...
– Tolu
Jan 8 at 10:14
add a comment |
Based on the code above, given that the workItem entity updated was loaded within the scope of the DB context and that the 2 values are strings, I'd have to say with 99.5% certainty that this code is not responsible for the behaviour you are seeing. (though I will definitely be watching this item to see if that is proven wrong:) I would be taking a close look at everywhere that either Status or StatusDetails is being used in relation to the calls made to the service. I suspect some other code is unexpectedly changing one or the other and calling SaveChanges.
A small optimization I can suggest:
var nextReviewer = context.WorkItemReviewers
.Where(r => r.WorkItemId == workItem.Id
&& r.Position > workItem.NextReviewerPosition)
.OrderBy(r => r.Position)
.Select(r => new { r.Position }) // Add any other details you may need from reviewer and other related entities.
.FirstOrDefault();
if (nextReviewer != null)
{
workItem.Status = "A";
workItem.StatusDetails = "A";
workItem.NextReviewerPosition = nextReviewer.Position;
//Other Code
}
else
{
workItem.Status = "B";
workItem.StatusDetails = "B";
workItem.NextReviewerPosition = null;
}
By using .Select()
you can optimize the query to just return back the columns from the tables you need which will make calls to the DB faster. Unless the query is expected to be relatively heavy in terms of time (> ~500ms for instance) I'd also avoid the async operation. It's purpose is to make the server more responsive when dealing with bigger operations. Using it on everything will make all operations a wee bit slower than necessary. Once you've optimized the data coming back, then async can be considered if it still requires a bit of time to chew through.
Based on the code above, given that the workItem entity updated was loaded within the scope of the DB context and that the 2 values are strings, I'd have to say with 99.5% certainty that this code is not responsible for the behaviour you are seeing. (though I will definitely be watching this item to see if that is proven wrong:) I would be taking a close look at everywhere that either Status or StatusDetails is being used in relation to the calls made to the service. I suspect some other code is unexpectedly changing one or the other and calling SaveChanges.
A small optimization I can suggest:
var nextReviewer = context.WorkItemReviewers
.Where(r => r.WorkItemId == workItem.Id
&& r.Position > workItem.NextReviewerPosition)
.OrderBy(r => r.Position)
.Select(r => new { r.Position }) // Add any other details you may need from reviewer and other related entities.
.FirstOrDefault();
if (nextReviewer != null)
{
workItem.Status = "A";
workItem.StatusDetails = "A";
workItem.NextReviewerPosition = nextReviewer.Position;
//Other Code
}
else
{
workItem.Status = "B";
workItem.StatusDetails = "B";
workItem.NextReviewerPosition = null;
}
By using .Select()
you can optimize the query to just return back the columns from the tables you need which will make calls to the DB faster. Unless the query is expected to be relatively heavy in terms of time (> ~500ms for instance) I'd also avoid the async operation. It's purpose is to make the server more responsive when dealing with bigger operations. Using it on everything will make all operations a wee bit slower than necessary. Once you've optimized the data coming back, then async can be considered if it still requires a bit of time to chew through.
answered Jan 6 at 21:52
Steve PySteve Py
6,19311020
6,19311020
Steve-py, thanks for this! My suspicion too is that the change is occurring elsewhere but I've not been able to pin it down. I'm up-voting this but I won't be accepting this as the answer just yet until I have full clarity. Thanks a bunch too for the suggestions on limiting the columns returned from the database and on async! I always thought async is at least just as fast and sometimes faster...
– Tolu
Jan 8 at 10:14
add a comment |
Steve-py, thanks for this! My suspicion too is that the change is occurring elsewhere but I've not been able to pin it down. I'm up-voting this but I won't be accepting this as the answer just yet until I have full clarity. Thanks a bunch too for the suggestions on limiting the columns returned from the database and on async! I always thought async is at least just as fast and sometimes faster...
– Tolu
Jan 8 at 10:14
Steve-py, thanks for this! My suspicion too is that the change is occurring elsewhere but I've not been able to pin it down. I'm up-voting this but I won't be accepting this as the answer just yet until I have full clarity. Thanks a bunch too for the suggestions on limiting the columns returned from the database and on async! I always thought async is at least just as fast and sometimes faster...
– Tolu
Jan 8 at 10:14
Steve-py, thanks for this! My suspicion too is that the change is occurring elsewhere but I've not been able to pin it down. I'm up-voting this but I won't be accepting this as the answer just yet until I have full clarity. Thanks a bunch too for the suggestions on limiting the columns returned from the database and on async! I always thought async is at least just as fast and sometimes faster...
– Tolu
Jan 8 at 10:14
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54023369%2fapparent-race-condition-concurrency-issue%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
You have omitted too much I think. What is
workItem
? How is it tracked and set? Is it a new entity instance or a retrieved one? Why is it relevant? If it is retrieved & tracked and the Status is set to the same value (ie. its "A" and you set it to "A" again) then it is ignored when you update it as it is not considered modified (by default). So that could result in a race condition.– Igor
Jan 3 at 17:17
BTW - I recommend you use unique constraints to avoid duble entries and use a versioning column like
rowversion
in sql server (I am not 100% sure how that translates into oracle but I assume there is a similar type). The later prevents race conditions and the first committing change wins, the later commit will receive an Exception which you can then handle.– Igor
Jan 3 at 17:21
In your code, are Status and StatusDetails both string types/primitive types, or are they references to other entities? Where is workItem declared, because I don't see from your example that it is associated to the context. I understand that it may seem prudent to obfuscate your actual code to hide proprietary details or attempt to simplify the issue, but this often leaves out key details that may explain your issue and leave people guessing at false positives that don't impact the real code.
– Steve Py
Jan 3 at 21:50
@Igor, I've edited slightly to show that work item is retrieved from the context.
– Tolu
Jan 4 at 22:25
@Steve Py, Status and Status details are strings.
– Tolu
Jan 4 at 22:25