Skip to content

Commit 602d259

Browse files
committed
fix: ObjectDisposedException in GetExceptionResult
1 parent c51878a commit 602d259

File tree

3 files changed

+28
-4
lines changed

3 files changed

+28
-4
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
- Added a `reset` method to all [API caller objects](https://intellitect.github.io/Coalesce/stacks/vue/layers/api-clients.html#api-callers). This method resets all stateful fields on the object to default values.
66
- Template: Added username/password auth option (aka individual user accounts, aka local accounts)
77

8+
## Fixes
9+
10+
- Fix an ObjectDisposedException from `StandardBehaviors.GetExceptionResult` when using an `IDbContextFactory` in an `Execute[Save|Delete]Async` implementation.
11+
12+
813
# 5.1.0
914

1015
## Features

src/IntelliTect.Coalesce.Tests/Tests/Api/Behaviors/SqlServerExceptionResultTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,25 @@ public void UniqueIndexConflict_UnknownIndex()
241241
Assert.Null(result);
242242
}
243243

244+
[Fact]
245+
public void DbContextIsDisposed()
246+
{
247+
Db.Add(new Product { UniqueId1 = "qwerty" });
248+
249+
var exception = CreateException(
250+
"Cannot insert duplicate key row in object 'dbo.Product' with unique index 'IX_Product_UniqueId1'. " +
251+
"The duplicate key value is (qwerty)");
252+
253+
// The context might dispose before GetExceptionResult is reached if the user is using an IDbContextFactory
254+
// with a `using` inside their ExecuteSaveAsync implementation.
255+
Db.Dispose();
256+
257+
var result = Behaviors<Product>()
258+
.GetExceptionResult(exception, new TestSparseDto<Product>() { ChangedProperties = { "UniqueId1" } });
259+
260+
result.AssertError("A different item with ID1 'qwerty' already exists.");
261+
}
262+
244263
private DbUpdateException CreateException(string error)
245264
{
246265
return new DbUpdateException("", CreateSqlException(547, error), Db.ChangeTracker.Entries().ToList());

src/IntelliTect.Coalesce/Api/Behaviors/StandardBehaviors`1.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -539,9 +539,9 @@ public virtual void AfterDelete(ref T item, ref IncludeTree? includeTree) { }
539539
return null;
540540
}
541541

542-
DbContext? dbContext = dbUpdateException.Entries.FirstOrDefault()?.Context;
542+
IModel? model = dbUpdateException.Entries.FirstOrDefault()?.Metadata.Model;
543543

544-
if (dbUpdateException.InnerException is not DbException dbException || dbContext is null)
544+
if (dbUpdateException.InnerException is not DbException dbException || model is null)
545545
{
546546
return null;
547547
}
@@ -560,7 +560,7 @@ public virtual void AfterDelete(ref T item, ref IncludeTree? includeTree) { }
560560
string table = match.Groups["table"].Value;
561561
string column = match.Groups["column"].Value;
562562

563-
var conflictedTable = dbContext.Model
563+
var conflictedTable = model
564564
.GetEntityTypes()
565565
.Where(t =>
566566
t.GetSchemaQualifiedTableName() == table ||
@@ -629,7 +629,7 @@ dependentEntity is not null &&
629629
string tableName = match.Groups["table"].Value;
630630
string keyValue = match.Groups["keyValue"].Value;
631631

632-
var table = dbContext.Model
632+
var table = model
633633
.GetEntityTypes()
634634
.FirstOrDefault(t =>
635635
t.GetSchemaQualifiedTableName() == tableName ||

0 commit comments

Comments
 (0)