Sql 对1:1的两侧可选关系建模

Sql 对1:1的两侧可选关系建模,sql,entity-framework,database-design,Sql,Entity Framework,Database Design,我有三个实体: 用户-可以有许多评论,也可以有许多交易 交易-必须有一个来自用户和用户,可以有来自用户审核或用户审核 查看-可以有交易,必须有来自用户和来自用户 这个想法是用户可以互相写评论,也可以互相付款。一个用户只能为另一个用户编写一个非事务性审阅-否则,审阅必须附加到事务 本质上,这成为交易和审查之间的1:1可选关系。我正在考虑使用包含以下内容的联接表对此进行建模: ReviewId TransactionId 并称之为TransactionReview。这似乎消除了模型/代码的重

我有三个实体:

  • 用户
    -可以有许多
    评论
    ,也可以有许多
    交易
  • 交易
    -必须有一个
    来自用户
    用户
    ,可以有
    来自用户审核
    用户审核
  • 查看
    -可以有
    交易
    ,必须有
    来自用户
    来自用户
这个想法是用户可以互相写评论,也可以互相付款。一个用户只能为另一个用户编写一个非事务性审阅-否则,审阅必须附加到事务

本质上,这成为交易和审查之间的1:1可选关系。我正在考虑使用包含以下内容的联接表对此进行建模:

  • ReviewId
  • TransactionId
并称之为TransactionReview。这似乎消除了模型/代码的重复,但使我的业务逻辑复杂化

我看到的另一种选择是创建两个实体:
UserReview
TransactionReview
——这将简化逻辑,但会迫使我重复代码,并为一个实体创建两个表


正确的方法是什么?我先使用实体框架代码,以防万一。

我可能会使用一个简单的数据模型:

  • 用户
  • 交易
    (此处不存储有关评论的信息)
  • 审查
    (审查必须针对特定用户或交易)
您可以根据评论的类型(字典表)来区分它,以了解哪个评论是独立的,哪个是事务附带的

你可以采取两种方式:

  • 有两列用于存储
    事务
    用户
    实体的ID,并根据类型保留空值
  • 或者,由于审查的类型,有一列可以识别实体的id
我认为不需要
TransactionReview
实体,因为一个审阅只能附加到0..1事务。由于事务可以有0..2个审核,因此这就变成了一对多关系,具有可选的零元素


我同意这可能会使检索逻辑复杂化(必须记住这一点),但我发现它在处理这样的建模数据时非常方便。

我已经准备了一些代码,请检查并尝试

public class User
{
    // properties
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual Address Address { get; set; }
    public virtual ICollection<UserReview> UserReviewsFromMe { get; set; }
    public virtual ICollection<UserReview> UserReviewsToUsers { get; set; }
    public virtual ICollection<TransactionReview> TransactionReviews { get; set; }
}

public class Review
{
    public int Id { get; set; }
    public string Content { get; set; }
    public string EntityName { get; set; }
    public int EntityId { get; set; }

    public virtual TransactionReview TransactionReview { get; set; }
    public virtual UserReview UserReview { get; set; }
}

public class Transaction
{
    public int Id { get; set; }
    public string Note { get; set; }
    public DateTime CreatedOnUtc { get; set; }

    public virtual ICollection<TransactionReview> TransactionReviews { get; set; }
}

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        ToTable("User");
        HasKey(p => p.Id);

    }
}

public class ReviewConfiguration : EntityTypeConfiguration<Review>
{
    public ReviewConfiguration()
    {
        ToTable("Review");
        HasKey(x => new { x.Id });
    }
}

public class TransactionConfiguration : EntityTypeConfiguration<Transaction>
{
    public TransactionConfiguration()
    {
        ToTable("Transaction");
        HasKey(x => new { x.Id });
    }
}

public class UserReview
{
    public int Id { get; set; }
    public int FromUserId { get; set; }
    public int ToUserId { get; set; }

    public virtual User FromUser { get; set; }
    public virtual Review Review { get; set; }
    public virtual User ToUser { get; set; }
}

public class TransactionReview
{
    public int Id { get; set; }
    public int TransactionId { get; set; }
    public int UserId { get; set; }

    public virtual Transaction Transaction { get; set; }
    public virtual Review Review { get; set; }
    public virtual User User { get; set; }
}

public class UserReviewConfiguration : EntityTypeConfiguration<UserReview>
{
    public UserReviewConfiguration()
    {
        ToTable("UserReview");
        HasKey(x => new { x.Id });
        Property(a => a.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);

        this.HasRequired(ur => ur.FromUser)
            .WithMany(u => u.UserReviewsFromMe)
            .HasForeignKey(ur => ur.FromUserId)
            .WillCascadeOnDelete(false);

        this.HasRequired(ur => ur.Review)
            .WithOptional(r => r.UserReview);

        this.HasRequired(ur => ur.ToUser)
            .WithMany(u => u.UserReviewsToUsers)
            .HasForeignKey(ur => ur.ToUserId)
            .WillCascadeOnDelete(false);
    }
}
公共类用户
{
//性质
公共int Id{get;set;}
公共字符串名称{get;set;}
公共虚拟地址{get;set;}
公共虚拟ICollection UserReviewFromme{get;set;}
公共虚拟ICollection UserReviewToUsers{get;set;}
公共虚拟ICollection TransactionReviews{get;set;}
}
公开课复习
{
公共int Id{get;set;}
公共字符串内容{get;set;}
公共字符串EntityName{get;set;}
public int EntityId{get;set;}
公共虚拟事务审阅事务审阅{get;set;}
公共虚拟UserReview UserReview{get;set;}
}
公共类事务
{
公共int Id{get;set;}
公共字符串注释{get;set;}
公共日期时间CreatedOnUtc{get;set;}
公共虚拟ICollection TransactionReviews{get;set;}
}
公共类UserConfiguration:EntityTypeConfiguration
{
公共用户配置()
{
ToTable(“用户”);
HasKey(p=>p.Id);
}
}
公共类审阅配置:EntityTypeConfiguration
{
公开评论配置()
{
可转帐(“审查”);
HasKey(x=>new{x.Id});
}
}
公共类TransactionConfiguration:EntityTypeConfiguration
{
公共事务配置()
{
可转帐(“交易”);
HasKey(x=>new{x.Id});
}
}
公共类用户评论
{
公共int Id{get;set;}
public int FromUserId{get;set;}
公共int ToUserId{get;set;}
公共虚拟用户FromUser{get;set;}
公共虚拟审阅{get;set;}
公共虚拟用户ToUser{get;set;}
}
公共类事务回顾
{
公共int Id{get;set;}
public int TransactionId{get;set;}
public int UserId{get;set;}
公共虚拟事务{get;set;}
公共虚拟审阅{get;set;}
公共虚拟用户用户{get;set;}
}
公共类UserReviewConfiguration:EntityTypeConfiguration
{
public UserReviewConfiguration()
{
ToTable(“用户评论”);
HasKey(x=>new{x.Id});
属性(a=>a.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);
this.HasRequired(ur=>ur.FromUser)
.WithMany(u=>u.UserReviewFromMe)
.HasForeignKey(ur=>ur.FromUserId)
.WillCascadeOnDelete(假);
此.HasRequired(ur=>ur.Review)
.WithOptional(r=>r.UserReview);
this.HasRequired(ur=>ur.ToUser)
.WithMany(u=>u.UserReviewToUsers)
.HasForeignKey(ur=>ur.tuserid)
.WillCascadeOnDelete(假);
}
}
在上面的UserReviewConfiguration类中,我是这样映射的:一个用户可以发布零个或多个UserReview,一个UserReview只能由一个用户发布,并且只能用于一个用户,并且只映射一个review,如果有人需要,也可以使review和用户实体独立

public class TransactionReviewConfiguration : EntityTypeConfiguration<TransactionReview>
{
    public TransactionReviewConfiguration()
    {
        ToTable("TransactionReview");
        HasKey(x => new { x.Id });
        Property(a => a.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None);

        this.HasRequired(tr => tr.Transaction)
            .WithMany(t => t.TransactionReviews)
            .HasForeignKey(tr => tr.TransactionId);

        this.HasRequired(tr => tr.Review)
            .WithOptional(r => r.TransactionReview);

        this.HasRequired(tr => tr.User)
            .WithMany(u => u.TransactionReviews)
            .HasForeignKey(tr => tr.UserId);
    }
}
公共类TransactionReviewConfiguration:EntityTypeConfiguration { 公共事务审阅配置() { ToTable(“交易审查”); HasKey(x=>new{x.Id}); 属性(a=>a.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None); this.HasRequired(tr=>tr.Transaction) 威斯康星州