{"id":23763898,"url":"https://github.com/tomashubelbauer/ef-cosmos-union-type","last_synced_at":"2026-08-17T09:32:29.996Z","repository":{"id":107986067,"uuid":"184587971","full_name":"TomasHubelbauer/ef-cosmos-union-type","owner":"TomasHubelbauer","description":"Representing union types in EF Core when using the Cosmos DB provider","archived":false,"fork":false,"pushed_at":"2022-04-14T20:08:59.000Z","size":8,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-05T18:59:56.684Z","etag":null,"topics":["ef","ef-core","entity-framework","entity-framework-core","union-types"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TomasHubelbauer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-05-02T13:41:04.000Z","updated_at":"2022-04-17T09:53:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"e33d5dfc-fd5c-42a8-9512-9a41e9cd7634","html_url":"https://github.com/TomasHubelbauer/ef-cosmos-union-type","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/TomasHubelbauer/ef-cosmos-union-type","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fef-cosmos-union-type","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fef-cosmos-union-type/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fef-cosmos-union-type/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fef-cosmos-union-type/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TomasHubelbauer","download_url":"https://codeload.github.com/TomasHubelbauer/ef-cosmos-union-type/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TomasHubelbauer%2Fef-cosmos-union-type/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":36739163,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-08-06T04:43:03.162Z","status":"online","status_checked_at":"2026-08-17T02:00:06.698Z","response_time":86,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ef","ef-core","entity-framework","entity-framework-core","union-types"],"created_at":"2024-12-31T22:13:49.486Z","updated_at":"2026-08-17T09:32:29.963Z","avatar_url":"https://github.com/TomasHubelbauer.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# EF Cosmos Union Type\r\n\r\nThis is not really a union type, but I didn't know what else to call it.\r\n\r\n1. `dotnet new console`\r\n2. `dotnet add package Microsoft.EntityFrameworkCore.Cosmos`\r\n3. `\u003cLangVersion\u003elatest\u003c/LangVersion\u003e` for `async Task Main`\r\n4. Ensure the Cosmos emulator is running\r\n5. Download the Cosmos key from the running instance to avoid versioning it\r\n6. Wire up the model as follows:\r\n\r\n```csharp\r\npublic sealed class Recurrence {\r\n  public Guid Id { get; set; }\r\n  public bool Monday { get; set; }\r\n  public bool Tuesday { get; set; }\r\n  public bool Wednesday { get; set; }\r\n  public bool Thursday { get; set; }\r\n  public bool Friday { get; set; }\r\n  public bool Saturday { get; set; }\r\n  public bool Sunday { get; set; }\r\n  public Unrecurrence Unrecurrence { get; set; }\r\n  public Exception[] Exceptions { get; set; }\r\n}\r\n\r\npublic abstract class Unrecurrence {\r\n  public Guid Id { get; set; }\r\n}\r\n\r\npublic sealed class UnrecurrenceByDate: Unrecurrence {\r\n  public DateTime DateAndTime { get; set; }\r\n}\r\n\r\npublic sealed class UnrecurrenceAtIndex: Unrecurrence {\r\n  public int RecurrenceIndex { get; set; }\r\n}\r\n\r\npublic abstract class Exception {\r\n  public Guid Id { get; set; }\r\n}\r\n\r\npublic sealed class ExceptionByDate: Exception {\r\n  public DateTime DateAndTime { get; set; }\r\n}\r\n\r\npublic sealed class ExceptionAtIndex: Exception {\r\n  public int RecurrenceIndex { get; set; }\r\n  public int SlotIndex { get; set; }\r\n}\r\n```\r\n\r\n7. Create EF context using the Cosmos key as follows:\r\n\r\n```csharp\r\npublic class AppDbContext: DbContext\r\n{\r\n  private string primaryKey;\r\n\r\n  public AppDbContext(string primaryKey)\r\n  {\r\n    this.primaryKey = primaryKey;\r\n  }\r\n\r\n  public DbSet\u003cRecurrence\u003e Recurrences { get; set; }\r\n  protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\r\n  {\r\n    optionsBuilder.UseCosmos(\"https://localhost:8081\", this.primaryKey, nameof(ef_cosmos_union_type));\r\n  }\r\n}\r\n```\r\n\r\n8. Try the naive approach:\r\n\r\n```csharp\r\nusing (var appDbContext = new AppDbContext(primaryKey))\r\n{\r\n  await appDbContext.Recurrences.AddAsync(new Recurrence\r\n  {\r\n      Monday = true,\r\n      Unrecurrence = new UnrecurrenceAtIndex { RecurrenceIndex = 10, },\r\n      Exceptions = new Exception[] {\r\n          new ExceptionByDate { DateAndTime = DateTime.Today },\r\n          new ExceptionAtIndex { RecurrenceIndex = 2, SlotIndex = 1 },\r\n      },\r\n  });\r\n}\r\n```\r\n\r\n9. F5 to run the VS Code debugger\r\n\r\nThe key is to use `HasBaseType` in `OnModelCreating`. See updated source code.\r\n\r\nThis stops working when embedded entities enter the picture.\r\nI will create a new demo for that: [ef-cosmos-embedded-inheritance](https://github.com/TomasHubelbauer/ef-cosmos-embedded-inheritance)\r\n\r\nI tried playing around with this a bit more.\r\nI renamed the `Exception` entity type to `Exception0` to make sure it is unique in the scope.\r\nI already knew that it resolved to the correct symbol but I wanted to make sure there wasn't a symbol resolution bug anyway.\r\nI added additional fluent API constraints - `HasOne` and `HasMany` on `Recurrence` for Unrecurrence and Exceptions respectively.\r\nI added IDs to all abstract and concrete types just in case and also unabstracted Unrecurrence and Exception0.\r\nI added manualy keys using the fluent API to Exception0 and Unrecurrence.\r\nI did all this based on the runtime model validator exceptions.\r\nAnd now I have the weirdest exception of all time which means it's probably time for an issue.\r\n\r\n## To-Do\r\n\r\n### Try to see if this will work with SQL Server\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomashubelbauer%2Fef-cosmos-union-type","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftomashubelbauer%2Fef-cosmos-union-type","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftomashubelbauer%2Fef-cosmos-union-type/lists"}