Skip to content

Commit

Permalink
Fix 'insert new only' for MySQL (#92)
Browse files Browse the repository at this point in the history
* Refactoring and added failing test.

* Fixed the issue.

* Bump the release version.
  • Loading branch information
videokojot authored Dec 17, 2023
1 parent 9e7a9aa commit a2e4d05
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public void BulkInsertOrUpdate_InsertOnlyNew_SetOutputIdentity(DbServerType dbTy
c.SetOutputIdentity = true;
});

var dbItems = GetItemsOfBulk(bulkId, dbType).OrderBy(x => x.GuidProperty).ToList();
var dbItems = db.GetItemsOfBulk(bulkId).OrderBy(x => x.GuidProperty).ToList();

var updatedDb = dbItems.Single(x => x.GuidProperty == initialItem.GuidProperty);
var newDb = dbItems.Single(x => x.GuidProperty == newItem.GuidProperty);
Expand Down Expand Up @@ -217,7 +217,7 @@ public void BulkInsertOrUpdate_WillNotSetOutputIdentityIfThereIsConflict(DbServe
Assert.Equal(BulkExtensionsExceptionType.CannotSetOutputIdentityForNonUniqueUpdateByProperties, exception.ExceptionType);
Assert.StartsWith("Items were Inserted/Updated successfully in db, but we cannot set output identity correctly since single source row(s) matched multiple rows in db.", exception.Message);

var bulkItems = GetItemsOfBulk(bulkId, dbType);
var bulkItems = db.GetItemsOfBulk(bulkId);

Assert.Equal(2, bulkItems.Count);

Expand Down Expand Up @@ -299,12 +299,7 @@ public void IUD_UpdateByCustomColumns_SetOutputIdentity_CustomColumnNames(DbServ
}
}

private List<SimpleItem> GetItemsOfBulk(Guid bulkId, DbServerType sqlType)
{
using var db = _dbFixture.GetDb(sqlType);

return db.SimpleItems.Where(x => x.BulkIdentifier == bulkId).ToList();
}

public class DatabaseFixture : BulkDbTestsFixture<SimpleBulkTestsContext>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public void BulkInsertOrUpdate_InsertNewOnly(DbServerType dbType)
});
}

var allItems = GetItemsOfBulk(bulkId, dbType);
var allItems = _dbFixture.GetDb(dbType).GetItemsOfBulk(bulkId);

Assert.Equal(2, allItems.Count);

Expand All @@ -82,12 +82,6 @@ public void BulkInsertOrUpdate_InsertNewOnly(DbServerType dbType)
Assert.Equal(initialItem.Name, itemWhichWasNotUpdated.Name);
}

private List<SimpleItem> GetItemsOfBulk(Guid bulkId, DbServerType sqlType)
{
using var db = _dbFixture.GetDb(sqlType);

return db.SimpleItems.Where(x => x.BulkIdentifier == bulkId).ToList();
}

public class DatabaseFixture : BulkDbTestsFixture<SimpleBulkTestsContext>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using EFCore.BulkExtensions.SqlAdapters;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
Expand All @@ -18,18 +19,19 @@ public MySqlBulkInsertOrUpdateTests(DatabaseFixture dbFixture)
_dbFixture = dbFixture;
}

[Fact(Skip = "Tracked by issue: https://github.com/videokojot/EFCore.BulkExtensions.MIT/issues/90")]
public async Task TestBulkInsertOrUpdate()
[Theory(Skip = "Tracked by issue: https://github.com/videokojot/EFCore.BulkExtensions.MIT/issues/90")]
[InlineData(DbServerType.MySQL)]
public async Task TestBulkInsertOrUpdate(DbServerType dbType)
{
var bulkId = Guid.NewGuid();
var initialItem = new MySqlItem()
{
Id = 0,
Name = "initialValue",
BulkId = bulkId,
StringProperty = "initialValue",
BulkIdentifier = bulkId,
};

using (var db = _dbFixture.GetDb(DbServerType.MySQL))
using (var db = _dbFixture.GetDb(dbType))
{
db.Items.Add(initialItem);
await db.SaveChangesAsync();
Expand All @@ -42,18 +44,18 @@ public async Task TestBulkInsertOrUpdate()
var updatingItem = new MySqlItem()
{
Id = initialId,
Name = "updatedValue",
BulkId = bulkId,
StringProperty = "updatedValue",
BulkIdentifier = bulkId,
};

var newItem = new MySqlItem()
{
Id = 0,
Name = "newValue",
BulkId = bulkId,
StringProperty = "newValue",
BulkIdentifier = bulkId,
};

using (var db = _dbFixture.GetDb(DbServerType.MySQL))
using (var db = _dbFixture.GetDb(dbType))
{
await db.BulkInsertOrUpdateAsync(new[]
{
Expand All @@ -63,22 +65,82 @@ await db.BulkInsertOrUpdateAsync(new[]
Assert.NotEqual(0, newItem.Id);
}

using (var db = _dbFixture.GetDb(DbServerType.MySQL))
using (var db = _dbFixture.GetDb(dbType))
{
var items = await db.Items.Where(x => x.BulkId == bulkId).ToListAsync();
var items = await db.Items.Where(x => x.BulkIdentifier == bulkId).ToListAsync();

Assert.Equal(2, items.Count);

// Item was updated
Assert.Single(items, x => x.Name == updatingItem.Name && x.Id == updatingItem.Id);
Assert.Single(items, x => x.StringProperty == updatingItem.StringProperty && x.Id == updatingItem.Id);

// Item was inserted
Assert.Single(items, x => x.Name == newItem.Name
Assert.Single(items, x => x.StringProperty == newItem.StringProperty
// && x.Id == newItem.Id
);
}
}

[Theory]
[InlineData(DbServerType.MySQL)]
public void BulkInsertOrUpdate_InsertNewOnly(DbServerType dbType)
{
var bulkId = Guid.NewGuid();

var initialItem = new MySqlItem()
{
StringProperty = "initial1",
BulkIdentifier = bulkId,
GuidProperty = Guid.NewGuid(),
};

using (var db = _dbFixture.GetDb(dbType))
{
db.Items.Add(initialItem);
db.SaveChanges();
}

var initialItemId = initialItem.Id;

// Should be inserted
var newItem = new MySqlItem()
{
Id = 0,
StringProperty = "insertedByBulk",
BulkIdentifier = bulkId,
GuidProperty = Guid.NewGuid(),
};

// Should not be updated (since we use insert only new scenario):
var updatedItem = new MySqlItem()
{
Id = initialItemId,
BulkIdentifier = bulkId,
StringProperty = "updated by Bulks",
GuidProperty = Guid.NewGuid(),
};

using (var db = _dbFixture.GetDb(dbType))
{
var ensureList = new[] { newItem, updatedItem };

db.BulkInsertOrUpdate(ensureList,
c => { c.PropertiesToIncludeOnUpdate = new() { "" }; });
}

var allItems = _dbFixture.GetDb(dbType).GetItemsOfBulk(bulkId);

Assert.Equal(2, allItems.Count);

var insertedItem = allItems.SingleOrDefault(x => x.GuidProperty == newItem.GuidProperty);
Assert.NotNull(insertedItem);

// initial item was not updated:
var itemWhichWasNotUpdated = allItems.Single(x => x.GuidProperty == initialItem.GuidProperty);
Assert.Equal(initialItem.Id, itemWhichWasNotUpdated.Id);
Assert.Equal(initialItem.StringProperty, itemWhichWasNotUpdated.StringProperty);
}

public class DatabaseFixture : BulkDbTestsFixture<MySqlSimpleContext>
{
protected override string DbName => nameof(MySqlBulkInsertOrUpdateTests);
Expand All @@ -91,15 +153,24 @@ public MySqlSimpleContext(DbContextOptions dbContextOptions) : base(dbContextOpt
}

public DbSet<MySqlItem> Items { get; private set; }

public List<MySqlItem> GetItemsOfBulk(Guid bulkId)
{
return Items.Where(x => x.BulkIdentifier == bulkId).ToList();
}
}

public class MySqlItem
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("DbId")]
public int Id { get; set; }

public string Name { get; set; }
public string StringProperty { get; set; }

public Guid BulkIdentifier { get; set; }

public Guid BulkId { get; set; }
public Guid GuidProperty { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;

namespace EFCore.BulkExtensions.Tests.BulkInsertOrUpdate;

Expand All @@ -21,6 +23,11 @@ public SimpleBulkTestsContext(DbContextOptions options)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}

public List<SimpleItem> GetItemsOfBulk(Guid bulkId)
{
return SimpleItems.Where(x => x.BulkIdentifier == bulkId).ToList();
}
}

public class SimpleItem
Expand Down
Loading

0 comments on commit a2e4d05

Please sign in to comment.