Trabalhando com transações MongoDB com C# e .NET Framework
Avalie esse Tutorial
Atualização 10/2019: o exemplo de código deste artigo foi atualizado para incluir o tratamento necessário do identificador de sessão para métodos de banco de dados.
Aplicativos C# conectados a um MongoDB database usam o driver MongoDB .NET. Para adicionar o driver .NET ao seu aplicativo Visual Studio, no NuGet Package Manager, pesquise "MongoDB".
Certifique-se de escolher a versão mais recente (>=2.7) do driver e pressione Install).
Antes da versão 4.0 do MongoDB, o MongoDB era transacionalmente consistente no nível do documento. Essas operações atômicas de documento único existentes fornecem a semântica de transação para atender às necessidades de integridade de dados da maioria dos aplicativos. Isso ocorre porque a flexibilidade do document model permite que os desenvolvedores incorporem facilmente dados relacionados a uma entidade como arrays e subdocumentos em um único documento avançado. Dito isto, há alguns casos em que a divisão do conteúdo em duas ou mais coleções seria apropriada e, para esses casos, as transações ACID de vários documentos tornam mais fácil do que nunca para os desenvolvedores abordarem toda a gama de casos de uso com o MongoDB . Para obter uma discussão mais detalhada sobre o design do document model do MongoDB, incluindo como representar relacionamentos um-para-muitos e muitos-para-muitos, confira este artigo sobre design de modelos de dados.
No código a seguir, criaremos um objeto Produto e executaremos uma transação no MongoDB que inserirá alguns dados de exemplo no MongoDB e, em seguida, atualizará os preços de todos os produtos em 10%.
1 using MongoDB.Bson; 2 using MongoDB.Bson.Serialization.Attributes; 3 using MongoDB.Driver; 4 using System; 5 using System.Threading.Tasks; 6 7 namespace MongoDBTransaction 8 { 9 public static class Program 10 { 11 public class Product 12 { 13 [ ]14 public ObjectId Id { get; set; } 15 [ ]16 public int SKU { get; set; } 17 [ ]18 public string Description { get; set; } 19 [ ]20 public Double Price { get; set; } 21 } 22 23 // replace with your connection string if it is different 24 const string MongoDBConnectionString = "mongodb://localhost"; 25 26 public static async Task Main(string[] args) 27 { 28 if (!await UpdateProductsAsync()) { Environment.Exit(1); } 29 Console.WriteLine("Finished updating the product collection"); 30 Console.ReadKey(); 31 } 32 33 private static async Task<bool> UpdateProductsAsync() 34 { 35 // Create client connection to our MongoDB database 36 var client = new MongoClient(MongoDBConnectionString); 37 38 // Create the collection object that represents the "products" collection 39 var database = client.GetDatabase("MongoDBStore"); 40 var products = database.GetCollection<Product>("products"); 41 42 // Clean up the collection if there is data in there 43 await database.DropCollectionAsync("products"); 44 45 // collections can't be created inside a transaction so create it first 46 await database.CreateCollectionAsync("products"); 47 48 // Create a session object that is used when leveraging transactions 49 using (var session = await client.StartSessionAsync()) 50 { 51 // Begin transaction 52 session.StartTransaction(); 53 54 try 55 { 56 // Create some sample data 57 var tv = new Product { Description = "Television", 58 SKU = 4001, 59 Price = 2000 }; 60 var book = new Product { Description = "A funny book", 61 SKU = 43221, 62 Price = 19.99 }; 63 var dogBowl = new Product { Description = "Bowl for Fido", 64 SKU = 123, 65 Price = 40.00 }; 66 67 // Insert the sample data 68 await products.InsertOneAsync(session, tv); 69 await products.InsertOneAsync(session, book); 70 await products.InsertOneAsync(session, dogBowl); 71 72 var resultsBeforeUpdates = await products 73 .Find<Product>(session, Builders<Product>.Filter.Empty) 74 .ToListAsync(); 75 Console.WriteLine("Original Prices:\n"); 76 foreach (Product d in resultsBeforeUpdates) 77 { 78 Console.WriteLine( 79 String.Format("Product Name: {0}\tPrice: {1:0.00}", 80 d.Description, d.Price) 81 ); 82 } 83 84 // Increase all the prices by 10% for all products 85 var update = new UpdateDefinitionBuilder<Product>() 86 .Mul<Double>(r => r.Price, 1.1); 87 await products.UpdateManyAsync(session, 88 Builders<Product>.Filter.Empty, 89 update); //,options); 90 91 // Made it here without error? Let's commit the transaction 92 await session.CommitTransactionAsync(); 93 } 94 catch (Exception e) 95 { 96 Console.WriteLine("Error writing to MongoDB: " + e.Message); 97 await session.AbortTransactionAsync(); 98 return false; 99 } 100 101 // Let's print the new results to the console 102 Console.WriteLine("\n\nNew Prices (10% increase):\n"); 103 var resultsAfterCommit = await products 104 .Find<Product>(session, Builders<Product>.Filter.Empty) 105 .ToListAsync(); 106 foreach (Product d in resultsAfterCommit) 107 { 108 Console.WriteLine( 109 String.Format("Product Name: {0}\tPrice: {1:0.00}", 110 d.Description, d.Price) 111 ); 112 } 113 114 return true; 115 } 116 } 117 } 118 }
- Você não precisa combinar propriedades de classe com objetos JSON. Basta definir um objeto de classe e inseri-lo diretamente no banco de dados. Não há necessidade de uma camada do mapeador relacional de objetos (ORM).
- As transações do MongoDB usam isolamento de snapshot, o que significa que somente o cliente envolvido na sessão transacional vê quaisquer alterações até o momento em que a transação seja confirmada.
- O driver .NET do MongoDB facilita o uso de transações e o uso da sintaxe baseada em LINQ para queries.
Informações adicionais sobre como usar C# e o driver .NET podem ser encontradas na documentação C# e driver .NET do MongoDB.