【问题标题】:Generating non primary key IDs using Entity Framework使用实体框架生成非主键 ID
【发布时间】:2019-01-29 09:53:27
【问题描述】:

您好,我想根据“主”类别生成非主键 ID。在下面显示的我的域模型中,lvl2 ID 是基于 lvl1 ID 生成的。我想我应该使用流利的 API 来做到这一点,但我还没有找到任何具体的例子。

它在 DB 中的外观示例如下:

ID  CatL1Id CatL1Name CatL2Id CatL2Name
1   1       PC        1       AllInOne
2   1       PC        2       Classic PC
3   2       Laptop    1       NetBook
4   2       Laptop    2       Class Laptop
5   3       Mac       1       MacBook Pro

我的领域模型是

public class Category
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int CategoryId { get; set; }

    public int CategoryLevel1Id { get; set; }

    public int CategoryLevel2Id { get; set; }

    public int CategoryLevel3Id { get; set; }

    public string CategoryLevel1Name { get; set; }

    public string CategoryLevel2Name { get; set; }

    public string CategoryLevel3Name { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

任何帮助表示赞赏!提前致谢

【问题讨论】:

  • @tanveery 评论的简单类别关系将解决您的问题。 Category on Category(可以在 Category 模型上定义一个 parentCategoryId 并连接 Category 表的主键)

标签: c# entity-framework


【解决方案1】:

您的域模型在转换为数据库表时将违反数据库规范化原则。

问题:类别实体中的级别列会造成冗余,更不用说如果您以后发现有更多级别需要容纳,则需要更改模型。

解决方案:这是我给你的建议:

步骤 1. 修改您的实体并创建父子关系,如下所示:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace DomainModel
{
    public class Category
    {
        public Category()
        {
            Children = new HashSet<Category>();
        }

        public int Id { get; set; }

        [Required]
        public string Name { get; set; }

        public int? ParentId { get; set; }

        public virtual ICollection<Category> Children { get; set; }

        public virtual Category Parent { get; set; }
    }
}

父子关系允许您根据需要创建任意多个级别。如果一个类别不属于某个级别(换句话说,它是一个根类别),则其父级将为空。

第 2 步。在 DbContext 类的 OnModelCreating() 方法中,指定如下关系:

modelBuilder.Entity<Category>()
    .HasMany(e => e.Children)
    .WithOptional(e => e.Parent)
    .HasForeignKey(e => e.ParentId);

数据库中的最终表如下所示:

【讨论】:

  • 这看起来像是要走的路。您可以发布您正在使用的“儿童”课程的代码吗?
  • 没有这样的儿童类。它是 Category 类的属性,将 Category 类的集合称为子类。
  • 知道了,之前没注意到。我会测试它并告诉你
【解决方案2】:

我会将该表拆分为两个表。一个用于 Cat1,一个用于 Cat2,具有 Cat1 的外键。这样您就不会有很多重复的 Cat1 条目,并且您可以轻松地将 Cat2 映射到正确的 Cat1。

这将使它成为 Cat1 和 Cat2 之间的一对多关系。

我不会担心 Id 值到底是什么,因为这无关紧要。
映射更重要,而且您的索引设置正确。

所以我想象的是这样的:

Category 1:
ID  CategoryLevel1Name 
1   PC
2   Laptop
3   Mac

Category 2:
ID  CategoryLevel1Id CategoryLevel2Name 
1   1                AllInOne
2   1                Classic PC
3   2                NetBook
4   2                Class Laptop
5   3                MacBook Pro

public class Category1
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string CategoryLevel1Name { get; set; }

    public ICollection<Category2> Category2s { get; set; }
}

public class Category2
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public int CategoryLevel1Id { get; set; }
    public string CategoryLevel2Name { get; set; }

    [ForeignKey("CategoryLevel1Id ")]
    public Category1 Category1 { get; set; }
}

免责声明:代码未经测试。

【讨论】:

  • 感谢您的回复 - 我犹豫是否使用此方法,因为每个新类别级别都必须创建新类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-02
  • 1970-01-01
  • 1970-01-01
  • 2017-10-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多