The extensions methods shown here can be applied in general in Entity Framework Core. In Azure Cosmos DB, if you use the
FindAsync method for example, you will not load the references of the item automatically.
Instead, you must explicitly go via
Entry method and then to LoadAsync on each
Reference.
A Reference is also called a navigational property in EF.
Let's first consider this code finding some Trip data item (data is stored in json format in Azure Cosmos DB since it is schema less and non-relational db or a 'document DB') and related data inside the
Driver, Address.
The POCO for Trip looks like this:
#region Info and license
#endregion
namespace TransportApp.Domain
{
public class Trip
{
public string TripId { get; set; }
public DateTime BeginUtc { get; set; }
public DateTime? EndUtc { get; set; }
public short PassengerCount { get; set; }
public string DriverId { get; set; }
public Driver Driver { get; set; }
public string VehicleId { get; set; }
public Vehicle Vehicle { get; set; }
public string FromAddressId { get; set; }
public Address FromAddress { get; set; }
public string ToAddressId { get; set; }
public Address ToAddress { get; set; }
}
}
We create a db context for Azure Cosmos DB like this :
private readonly IDbContextFactory _contextFactory;
public SomeService(IDbContextFactory contextFactory)
{
_contextFactory = contextFactory;
//..
}
public async Task RunSomeDemoCode(){
using var context = await contextFactory.CreateDbContextAsync();
}
Once we have our
context object we can get data from Azure Cosmos DB.
public async Task RunSomeDemoCode(){
using var context = await contextFactory.CreateDbContextAsync();
var trip1 = await otherContext.Trips.FindAsync($"{nameof(Trip)}-1");
await otherContext.LoadEntityWithAllReferences(trip1!);
}
Note that we probably want to check that trip1 object is not null here. We want to get the
relations also here. This is not automatically loaded in Azure Cosmos DB ! We can load the
relations or
navigational properties using the following extensions methods listed below. If you use the method accepting an EntityEntry, you must use the
Entry method first, like shown in the other method.
public static class EntityEntryExtensions
{
public static async Task LoadAllReferences<T>(this EntityEntry<T> entry) where T : class
{
foreach (var reference in entry.References)
{
await reference.LoadAsync();
}
}
}
public static class EntityExtensions
{
public static async Task LoadEntityWithAllReferences<T>(this DbContext dbContext, T dataItem) where T : class
{
if (dataItem == null)
{
return;
}
var entity = dbContext.Entry(dataItem!);
foreach (var reference in entity.References)
{
await reference.LoadAsync();
}
}
}
I have added two screenshots here, first before calling the method
LoadEntityWithAllReferences, and afterwards.
Before:
After:
As we can see from the screen shots, the references has been loaded and now you avoid to manually have to load one and one reference property / navigation property.
Note - about some of the sample code - it came from a Pluralsight Course. I have looked more into the extension methods here myself.
/*
This demo application accompanies Pluralsight course 'Using EF Core 6 with Azure Cosmos DB',
by Jurgen Kevelaers. See https://pluralsight.pxf.io/efcore6-cosmos.
MIT License
Copyright (c) 2022 Jurgen Kevelaers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
No comments:
Post a Comment