Azure Mobile Apps v8.0 #802
Replies: 10 comments 20 replies
-
EF Core on client side is very interesting for standard LINQ for SQLite and customizable sync (override SaveChanges/Async) as you said |
Beta Was this translation helpful? Give feedback.
-
Using EF Core should also simplify cases such as #804 |
Beta Was this translation helpful? Give feedback.
-
I'm excited about this potential direction as it sounds like it could address many of the things we are already trying to do through workarounds to the current limitations. How significant do you expect the changes to be to the current API surface (both client and server)? We are currently dealing with one-to-many and many-to-many relationships between synchronized tables and one of the challenges is synchronizing insertions vs synchronizing deletions in correct orders. Right now, where the master is centralized at the server, and client db's aren't also "masters" the concept of "hard" deletions on the client make it harder (but not impossible) to enforce foreign key constraints across tables during synchronization. Curious how you're thinking of handling this?
This makes me think that the client database will at least have some historical state data, at least as far as deletion states are concerned (i.e. current state only, but no history). Or are you planning on more than just that? Would there be the potential to have the option of having a historical ledger to support multi master merging or version rollbacks? (i.e. https://github.com/vlcn-io/cr-sqlite#how-does-it-work) Also going to EF Core opens options to support nested JSON queries: dotnet/efcore#28816. Would you still support the same client query features locally ( |
Beta Was this translation helpful? Give feedback.
-
One of the main problems I struggle with is handling user access per table. Let's say I have table A with field userId, which I use to filter records designated for given user, i.e. in the backend I have my own AccessProvider set for the Controller of table A where I filter the table based on token data from the request. Let's say table A is linked to table B (1:N). The approach is the same but now the accessor needs to query table A first. Let's say there is table C linked to table table B, so now it's 1:N:N relationship. Naturally it all becomes very ugly. If we can have full fledged offline database with relationships, it would be nice if it can pull data from tables B and C based on the relationship constrains. |
Beta Was this translation helpful? Give feedback.
-
A quickie update on where we are at with v8 at this time. This week, I'm concentrating on "live repository tests". There is an infra folder that deploys an Azure SQL, PostgreSQL, and Cosmos DB database, and each supported database will get a common set of tests. The tests can easily be re-used for your own repositories as well. You basically create a test class that inherits from Right now, there are issues all over the place:
If you want to do the live tests yourself (and you are working with the v8 branch), then you have to create a .runsettings file or set environment variables (before running dotnet test). Specifically, set these environment variables to the appropriate connection string:
I'll add a My aim is for 100% coverage of the repositories by the end of the week so that I have confidence that the "supported databases" actually work, and to give folks a set of DbContext classes that they can use as models for their own work. My list of supported repositories / databases:
I did get with the Cosmos DB folks about having a native Cosmos/SQL implementation. The only real way to do this is to have /id be the partition key, or to do cross-partition queries (which are expensive), or to do something custom (i.e. don't have a standard library). The problem is that our offline "promise" is that the offline client can generate an ID. If you package the partition key inside the ID, you are enforcing a format on the ID which breaks that offline "promise". So, at best, we have to write code that says "on create, the ID may change". This creates further problems in offline change tracking and data binding. My intent is to have better documentation around repository writing, so I'm going to use a specialist Cosmos repository as the example and let folks write the Cosmos based repository themselves based on the documentation. The official Cosmos support will be via Entity Framework Core. Cosmos does have "other facets" - PostgreSQL, MongoDB, etc. Do you all want me to add tests / instructions for those facets as well? |
Beta Was this translation helpful? Give feedback.
-
Quickie update - now that .NET8 is out and LTS, the v8 branch will be upgraded to .NET 8 over the next couple of weeks. |
Beta Was this translation helpful? Give feedback.
-
I notice this thread is related to using joins in the offline database. So I am assuming joins do work already using the remote tables. Can you please point me to a sample if any of how we can use a View to fetch data from 2 or more tables? FYI we're using the 6.0.4 version of the library with a MAUI app. |
Beta Was this translation helpful? Give feedback.
-
Hey folks - another update for my post-Christmas work. The server now supports GeoJSON!!!!! This includes including GeographyPoint and GeometryPoint in the server-side model, and using geo.distance(p0, p1) (where either p0 or p1 can be a field in your model or geography'POINT(a b)' to indicate a static value for the GeographyPoint. Note that GeographyPoint and GeometryPoint are part of the Microsoft.Spatial library which is an ABSTRACTION of a Geo location. You would likely need to transform these before storing in the database. You can do this either by doing GeographyPoint.Create(x y) and storing longitude and latitude OR by transforming to NetTopologySuite (or another library that supports your provider). Almost done with the server side at this point (just a few more tests to write for corner cases). I've also started work on the client side, but not much has been done there yet. |
Beta Was this translation helpful? Give feedback.
-
Adrian, On the Controller side, in particular the Repository, I am modifying your class to enable more complex filtering to manage user access permission to the database tables which needs to only allow data back to the client depending on their permission levels across users and tenants etc. I think I saw another similar discussion on this https://github.com/Azure/azure-mobile-apps/issues/873#issuecomment-1890660271 . As an example on our Blazor API controller we use MediatR and pass a query or command in which the dbcontext is accessed and with linq do any permission checking and querying we want and to return entities or results. Its not really the MediatR pattern Im raising but the beauty of the complete control one has by defining query and command classes that can be passed to something like MediatR. A Respository redesign could be a nice improvement although it will more than serve my purposes as is since I can modify myself scott |
Beta Was this translation helpful? Give feedback.
-
In https://github.com/Azure/azure-mobile-apps/issues/838, support was asked for encryption of the on-device SQLite database. I saw you already made a solution for that 👍🏼, and I was wondering whether that route will keep working when azure-mobile-apps will switch to EF Core? |
Beta Was this translation helpful? Give feedback.
-
Hey folks,
I've been doing a little bit of experimentation on another repo to try and solve two basic problems with Azure Mobile Apps.
I'm also researching how to support one-to-many relationships in the offline database. These things seem to come up frequently in discussions and issues. Fortunately, I believe I have found a way to do both of these, but it fundamentally changes how we think of Azure Mobile Apps.
In the current version, we instantiate a client, which is a representation of the REMOTE service. The offline bit is an extension of the remote service. You can have communication with the service and no offline database, but you can't have the reverse. In order to re-orientate the capability to be offline first, we have to start thinking that the offline database is first, and remote connectivity is an optional extra.
To support this, I believe that we need to switch the central capability to be an Entity Framework Core database context. We can override the SaveChanges() and SaveChangesAsync() methods to maintain the offline operations queue, then provide an optional synchronization provider that synchronizes the data to the remote service.
This new architecture will, I believe, allow us to support all of the LINQ queries that are supported by SQLite as well as allow us to support additional synchronization mechanisms beyond the OData+REST mechanism we use today. It will also give you all more control over the database capabilities. I've seen requests, for example, for offline only data - this would now be possible by having an offline only table and then joining it with the online table with LINQ.
I'm going to start a new branch (likely to be called v8 or rearch) to do the work - which will be extensive. I should note that while the architecture is solid (I've passed it around a number of folks here at Microsoft to validate it), there is no guarantee that it will be adopted.
This process also depends on YOUR input. I'll explicitly need you to try out the new architecture in your applications so we can come up with guidance around migrating from the v6 version to the v8 version. If you would like to write samples for MAUI, WinUI3, WPF, Avalonia, or Uno, then I'd love to hear from you.
Unfortunately, because of the reliance of this on Entity Framework Core, I'll be limiting the v8 version to .NET 6 and beyond. Ideally, I'd like this to work with the latest .NET 8 when it reaches release in a few weeks, but I also want it to be backwards compatible to .NET 6 while that is still supported by Microsoft.
For those of you still developing .NET Standard, UWP, and Xamarin apps, the 6.0 train will be the last train to support these platforms. It's not going anywhere. I'll just be cutting a 6.0 branch right before I merge in the 8.0 branch to main.
Feel free to put your questions in the comments below. I CRAVE YOUR FEEDBACK ON THIS. Don't be shy - no stupid questions. Let's prod and poke at this new direction to make sure it's a good one.
Beta Was this translation helpful? Give feedback.
All reactions