SapphireDb logo SapphireDb

Include/Join

If you are using relations in you database you sometimes want to resolve them on server side and get the complete object to the client.
You can control that by using the include operation (It works like the include operation of EF Core). It will perform a join operation on database side.

Example

This example consists of two models: A user object with entries and the entries with a reference to the user.

Display users with entries

This basic example shows how to query data with its navigation properties included

Note that the complete referenced object is loaded when using a join operation. No check for auth will be made. The result contains the complete object.
\f:(typescript:Angular) export class DemoComponent implements OnInit {\n \tprivate userCollection: DefaultCollection<User>;\n \tpublic users$: Observable<User[]>;\n\n \tconstructor(private db: SapphireDbService) {\n \t\tthis.userCollection = this.db.collection('Users').include('entries');\n \t\tthis.users$ = this.userCollection.values();\n \t}\n } \f:(csharp:User.cs:Server) public class User\n {\n \t[Key]\n \tpublic Guid Id { get; set; }\n\n \tpublic List<Entry> Entries { get; set; }\n\n \tpublic string Name { get; set; }\n } \f:(csharp:Entry.cs:Server) public class Entry\n {\n \t[Key]\n \tpublic Guid Id { get; set; }\n\n \t[ForeignKey("User")]\n \tpublic Guid UserId { get; set; }\n\n \tpublic User User { get; set; }\n\n \tpublic string Content { get; set; }\n } \f:(csharp:DatabaseContext.cs:Server) public class DemoContext : SapphireDbContext\n {\n \tpublic DemoContext(DbContextOptions<DemoContext> options, SapphireDatabaseNotifier notifier) : base(options, notifier) {}\n\n \tpublic DbSet<User> Users { get; set; }\n \tpublic DbSet<UserEntry> UserEntries { get; set; }\n }

Create/Update user entries

You can also update/create entries that are loaded by including them in the normal update operations.

Creating/Updating objects through the navigation property is not always recommended because the operation ignores all specified auth rules.
If you want to disable the possibility to edit the values using this way remove the [Updatable]-attribute from the navigation property and add the attribute [NonCreatable] to it.
\f:(typescript:Angular) export class DemoComponent implements OnInit {\n \tprivate userCollection: DefaultCollection<User>;\n \tpublic users$: Observable<User[]>;\n\n \tconstructor(private db: SapphireDbService) {\n \t\tthis.userCollection = this.db.collection('Users').include('entries');\n \t\tthis.users$ = this.userCollection.values();\n \t}\n } \f:(csharp:User.cs:Server) public class User\n {\n \t[Key]\n \tpublic Guid Id { get; set; }\n\n \t// Update and creation of entries is possible\n \t[Updatable]\n \tpublic List<Entry> Entries { get; set; }\n\n \tpublic string Name { get; set; }\n } \f:(csharp:UserDisabled.cs:Server) public class User\n {\n \t[Key]\n \tpublic Guid Id { get; set; }\n\n \t// No update or creation of entries is possible\n \t[NonCreatable]\n \tpublic List<Entry> Entries { get; set; }\n\n \tpublic string Name { get; set; }\n }

Display entries with user

\f:(typescript:Angular) export class DemoComponent implements OnInit {\n \tcollection: DefaultCollection<Entry>; \tvalues$: Observable<Entry[]>;\n\n \tconstructor(private db: SapphireDbService) { }\n\n \tngOnInit() {\n \t\tthis.collection = this.db.collection('Entries').include('user');\n \t\tthis.values$ = this.collection.values();\n \t}\n }
You have to take note of the special behavior when using include operations:
  • The related objects are loaded without checking for authorization. All related values and fields will get loaded.
  • It is possible to create/update new objects when putting them in the navigation property
  • You can control the behavior of updating/creating navigation properties by using the attributes [Updatable] and [NonCreatable]
  • It is recommended to mark all navigation properties with [NonCreatable]. This will force you to create/update objects using the methods on the specific collections.
  • When anything in the database changes that is related to the loaded data, the complete query gets executed again. That can have a negative impact on performance.

This website uses Google Analytics. If you want to disable it just unselect the option: