EF Core 中具有私有字段和类型转换的多对多

发布于 2025-01-10 20:50:00 字数 1567 浏览 2 评论 0原文

我尝试将多对多关系与私有字段的数据类型转换映射。我不需要公共属性,因为我希望能够从产品添加新的 CategoryId 和从类别添加新的 ProductId 但我不想从数据库查询它们并公开外面的那些田地。

public class Product : Aggergate
{
     private readonly List<CategoryId> _categoryIds;

     public void AddCategory(CategoryId category)
     {
          _categoryIds.Add(category);
     }
}


public class Category : Aggergate
{
     private readonly List<ProductId> _productIds;

     public void AddProduct(ProductId product)
     {
          _productIds.Add(product);
     }
}

注意:CategoryIdProductId 封装标识符如下:

public class CategoryId : ValueObject
{
     public int Value { get; private set; }
     public CategoryId(int value)
     {
          Value = value;

     }
}

我不想直接在 Product 和 Category 中引用关联域,因为我尝试使用 DDD 方法对实体进行建模。

我尝试使用 .UsingEntity(e => e.ToTable("CategoryProductTbl") 进行映射,但无法使用此方法配置约定。

我尝试创建其他实体 ProductCategory 并将其用于仅映射级别,例如:

builder.HasMany<CategoryId>("_categoryIds")
     .WithMany("_productIds")
     .UsingEntity<ProductCategory>("ProductCategory",
     j => j.HasOne(x => x.Category)
          .WithMany("_categoryIds")
          .HasForeignKey(x => x.CategoryId),
     j => j.HasOne(x => x.ProductType)
          .WithMany("_productTypesIds")
          .HasForeignKey(x => x.ProductTypeId));

但我必须为 List 添加转换(据我所知这是不可能的)

是吗在我的示例中可以配置多对多吗?

I try to map many-to-many relation with data type conversion for private fields. I don't want public properties because I want to be able to add new CategoryId from Product and ProductId from Category but I don't want to query them from db and expose those fields outside.

public class Product : Aggergate
{
     private readonly List<CategoryId> _categoryIds;

     public void AddCategory(CategoryId category)
     {
          _categoryIds.Add(category);
     }
}


public class Category : Aggergate
{
     private readonly List<ProductId> _productIds;

     public void AddProduct(ProductId product)
     {
          _productIds.Add(product);
     }
}

note: CategoryId and ProductId encapsulated identifier like this:

public class CategoryId : ValueObject
{
     public int Value { get; private set; }
     public CategoryId(int value)
     {
          Value = value;

     }
}

I don't want to referene associative domain directly in Product and Category because I try to model entities with DDD approach.

I tried to map with .UsingEntity(e => e.ToTable("CategoryProductTbl") but I can't configure convensions using this approach.

I tried to create additional entity ProductCategory and use it for mapping only level like:

builder.HasMany<CategoryId>("_categoryIds")
     .WithMany("_productIds")
     .UsingEntity<ProductCategory>("ProductCategory",
     j => j.HasOne(x => x.Category)
          .WithMany("_categoryIds")
          .HasForeignKey(x => x.CategoryId),
     j => j.HasOne(x => x.ProductType)
          .WithMany("_productTypesIds")
          .HasForeignKey(x => x.ProductTypeId));

But I would have to add conversion for List<CategoryId> (it's impossible for collections afaik)

Is it possible to configure many-to-many in my example?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

花期渐远 2025-01-17 20:50:00

您实际上并不需要多对多,因为它用于创建跳过链接表的导航属性,而您说您不希望这样做。因此,实际上您只想将链接表添加为常规实体,而没有其自己的任何导航属性。

例如

public class Aggregate
{
    public int Id { get; set; }
}
internal class ProductCategory
{
    public int ProductId { get; set; }
    public int CategoryId { get; set; }
}
public class Product : Aggregate
{
    private readonly List<ProductCategory> productCategories = new List<ProductCategory>();

    public void AddCategory(int categoryId)
    {
        productCategories.Add(new ProductCategory() { CategoryId = categoryId, ProductId = this.Id});
    }
}

public class Category : Aggregate
{
    private readonly List<ProductCategory> productCategories = new List<ProductCategory>();

    public void AddProduct(int productId)
    {
        productCategories.Add(new ProductCategory() { CategoryId = this.Id, ProductId = productId});
    }
}


public class Db : DbContext
{
    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<Product>()
               .HasMany("productCategories")
               .WithOne();

        builder.Entity<Category>()
               .HasMany("productCategories")
               .WithOne();

        builder.Entity<ProductCategory>()
               .HasKey(c => new { c.ProductId, c.CategoryId });

        base.OnModelCreating(builder);

    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=localhost;database=efCore6Test;Integrated Security=true;TrustServerCertificate=true", o => o.UseRelationalNulls(true))
            .LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information);
        base.OnConfiguring(optionsBuilder);
    }
}

You don't actually want Many-to-Many, because that is used to create Navigation Property that skips the linking table, which you said you don't want. So actually you just want to add the linking table as a regular entity without any Navigation properties of its own.

Eg

public class Aggregate
{
    public int Id { get; set; }
}
internal class ProductCategory
{
    public int ProductId { get; set; }
    public int CategoryId { get; set; }
}
public class Product : Aggregate
{
    private readonly List<ProductCategory> productCategories = new List<ProductCategory>();

    public void AddCategory(int categoryId)
    {
        productCategories.Add(new ProductCategory() { CategoryId = categoryId, ProductId = this.Id});
    }
}

public class Category : Aggregate
{
    private readonly List<ProductCategory> productCategories = new List<ProductCategory>();

    public void AddProduct(int productId)
    {
        productCategories.Add(new ProductCategory() { CategoryId = this.Id, ProductId = productId});
    }
}


public class Db : DbContext
{
    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<Product>()
               .HasMany("productCategories")
               .WithOne();

        builder.Entity<Category>()
               .HasMany("productCategories")
               .WithOne();

        builder.Entity<ProductCategory>()
               .HasKey(c => new { c.ProductId, c.CategoryId });

        base.OnModelCreating(builder);

    }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("Server=localhost;database=efCore6Test;Integrated Security=true;TrustServerCertificate=true", o => o.UseRelationalNulls(true))
            .LogTo(Console.WriteLine, Microsoft.Extensions.Logging.LogLevel.Information);
        base.OnConfiguring(optionsBuilder);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文