diff --git a/MongoIncUpdate.Base/IncUpdate.cs b/MongoIncUpdate.Base/IncUpdate.cs index 7893855..eb81a8c 100644 --- a/MongoIncUpdate.Base/IncUpdate.cs +++ b/MongoIncUpdate.Base/IncUpdate.cs @@ -1,10 +1,14 @@ -using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; using MongoDB.Driver; namespace MongoIncUpdate.Base; public static class IncUpdateExt { + static readonly ReplaceOptions ReplaceOptions = new() { IsUpsert = true }; + static readonly UpdateOptions UpdateOptions = new() { IsUpsert = true }; + public static object? GetBsonId(this T self) where T : class { var find = typeof(BsonIdAttribute); @@ -16,36 +20,42 @@ public static class IncUpdateExt return null; } - public static async Task IncUpdate(this IMongoCollection collection, T item) where T : class + public static async Task IncUpdate(this IMongoCollection collection, T item, + bool forceReplace = false) where T : class { //获取bsonId。这种方式性能较低,但比较通用。 var id = item.GetBsonId(); if (id == null) throw new Exception("BsonId not exist"); - - var diffUpdateable = item as IDiffUpdateable; - var defs = new List>(); - diffUpdateable?.BuildUpdate(defs, ""); - //无数据更新直接跳过 - if (defs.Count == 0) return new UpdateResult.Acknowledged(0, 0, 0); - //更新 - var setter = Builders.Update.Combine(defs); - var filter = Builders.Filter.Eq("_id", id); - Console.WriteLine($"update data count:{defs.Count}"); - return await collection.UpdateOneAsync(filter, setter, new UpdateOptions { IsUpsert = true }); + return await collection.IncUpdate(item, id, forceReplace); } - public static async Task IncUpdate(this IMongoCollection collection, T item, TK id) - where T : class + public static async Task IncUpdate(this IMongoCollection collection, T item, TK id, + bool forceReplace = false) + where T : class where TK : notnull { - var diffUpdateable = item as IDiffUpdateable; - var defs = new List>(); - diffUpdateable?.BuildUpdate(defs, ""); - //无数据更新直接跳过 - if (defs.Count == 0) return new UpdateResult.Acknowledged(0, 0, 0); - //更新 - var setter = Builders.Update.Combine(defs); var filter = Builders.Filter.Eq("_id", id); - Console.WriteLine($"update data count:{defs.Count}"); - return await collection.UpdateOneAsync(filter, setter, new UpdateOptions { IsUpsert = true }); + if (forceReplace) //强制全量替换 + { + var result = await collection.ReplaceOneAsync(filter, item, ReplaceOptions); + return new UpdateResult.Acknowledged(result.MatchedCount, result.ModifiedCount, result.UpsertedId); + } + + try //优先增量更新 + { + var diffUpdateable = item as IDiffUpdateable; + var defs = new List>(); + diffUpdateable?.BuildUpdate(defs, ""); + //无数据更新直接跳过 + if (defs.Count == 0) return new UpdateResult.Acknowledged(1, 0, null); + //更新 + var setter = Builders.Update.Combine(defs); + // Console.WriteLine($"update data count:{defs.Count}"); + return await collection.UpdateOneAsync(filter, setter, UpdateOptions); + } + catch (Exception) //增量更新失败则退化为全量替换(逻辑上没上用,增量异常了全量替换也大概率一场--仅仅是为了保证逻辑完整--) + { + var result = await collection.ReplaceOneAsync(filter, item, ReplaceOptions); + return new UpdateResult.Acknowledged(result.MatchedCount, result.ModifiedCount, result.ToBson()); + } } } \ No newline at end of file diff --git a/MongoIncUpdate.Fody.Test/IncUpdateTests.cs b/MongoIncUpdate.Fody.Test/IncUpdateTests.cs index db4cd56..e4590a3 100644 --- a/MongoIncUpdate.Fody.Test/IncUpdateTests.cs +++ b/MongoIncUpdate.Fody.Test/IncUpdateTests.cs @@ -119,7 +119,7 @@ public async Task TestSampleInt() _output.WriteLine("全量写入"); var cc = _db.GetCollection(nameof(ItemInt)); var a = new ItemInt { Id = 1, I = 2 }; - _ = await cc.IncUpdate(a, 1); + _ = await cc.IncUpdate(a, 1, true); _output.WriteLine("全量写入检查"); var filer = Builders.Filter.Eq(x => x.Id, a.Id); var result = (await cc.FindAsync(filer)).First();