aws-samples / aws-dynamodb-examples

DynamoDB Examples
Apache License 2.0
541 stars 210 forks source link

Entity Framework Support #112

Open harrypooni-118 opened 1 month ago

harrypooni-118 commented 1 month ago

Will there be support for EF Core with DynamoDb to utilise LINQ expression when querying tables and take advantage of EF Core. MongoDB and CosmosDB is fully supported in EF Core, DynamoDB is the only one left out.

tebanieo commented 1 month ago

Hello Harry, thanks for creating this issue, natively does not provide any ORM, at this point. Having said that I will create a Product Feature Request in your behalf. Please provide additional information about your use case, the necessity for this, and the implications of lacking native support. I intend to keep the issue open in order to collect as much information as possible, which will let me give feedback to the service team.

harrypooni-118 commented 1 month ago

Thanks @tebanieo Some of the key features is configuring the mapping between the POCO Properties, querying data via a LINQ expression and support for transactions. I know DynamoDB can perform these requests outside of EF Core using the SDK, however the LINQ expression to query data is on the missing key components to provide a better developer experience.

These capabilities can extend other libraries such MassTransit for outbox pattern integration. At the moment almost all devs have to use 2 separate data sources to use the MassTransit outbox pattern when coupled with DynamodDB, due to no EF Core support.

harrypooni-118 commented 3 weeks ago

Here is an example config that EF Core offers to simply the integration with data sources. These example below highlights how to configure the dbcontext and configure the entity you want to set within the context. This has come from a RD database, but the principal is the same. More than happy to assist with a nosql equivalent. There is a few examples for MongoDb on the web.

public class OrderDbContext: DbContext
{
    public OrderDbContext(DbContextOptions<OrderDbContext> options) : base(options)
    {
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder
            .UseInMemoryDatabase(Guid.NewGuid().ToString()); // SameName = Shared in memory database across all unit tests  
    }

    public DbSet<Order> Orders { get; set; } = null!;
    public DbSet<OrderLine> OrderLines { get; set; } = null!;

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfiguration(new OrderMapConfig());
    }
}

public class OrderMapConfig : IEntityTypeConfiguration<Order>
{
    public void Configure(EntityTypeBuilder<Order> builder)
    {
        builder.ToTable("Orders");
        builder.HasKey(_ => _.Id);
        builder.OwnsMany(_ => _.OrderLines, sb =>
        {
            sb.HasKey(_ => _.Id);
            sb.Property(_ => _.Id).ValueGeneratedOnAdd().UsePropertyAccessMode(PropertyAccessMode.Property);
            sb.Property(_ => _.OrderId).UsePropertyAccessMode(PropertyAccessMode.Property);
            sb.WithOwner().HasForeignKey(_ => _.OrderId);
            sb.ToTable("OrderLines");
        });
        builder.Property(_ => _.Id).ValueGeneratedOnAdd();
        builder.Property(_ => _.OrgId).UsePropertyAccessMode(PropertyAccessMode.Property);
        builder.Property(_ => _.OrgUnit).UsePropertyAccessMode(PropertyAccessMode.Property);
        builder.Navigation(_ => _.OrderLines).AutoInclude().UsePropertyAccessMode(PropertyAccessMode.Property);
        builder.Property(_ => _.CreatedAt).UsePropertyAccessMode(PropertyAccessMode.Property);
        builder.Property(_ => _.UpdatedAt).UsePropertyAccessMode(PropertyAccessMode.Property);
        builder.Ignore(_ => _.DomainEvents);
    }
}