2016-08-17 3 views
1

У меня есть три сущности:Моделирование 1: 1 опциональных-на-как-сайд отношений

  • User - может иметь много Reviews и могу иметь много Transactions
  • Transaction - должны иметь FromUser и ToUser, может иметь FromUserReview или ToUserReview
  • Review - может иметь Transaction, должны иметь FromUser и ToUser

Идея состоит в том, что пользователи могут писать отзывы друг на друга, могут отправлять платежи друг другу. Пользователь может писать только один транзакционный обзор для другого пользователя - в противном случае к транзакциям должны прилагаться обзоры.

По существу, это становится взаимозависимым между транзакциями и отзывами на 1: 1. Я думал о моделировании это с присоединиться к таблице, которая содержит:

  • ReviewId
  • TransactionId

И назвав его TransactionReview. Это, похоже, устраняет дублирование модели/кода, но усложняет мою бизнес-логику.

Другая альтернатива, которую я вижу, заключается в создании двух объектов: UserReview и TransactionReview - что упростит логику, но заставит меня повторить код и иметь две таблицы для того, что должно быть одним объектом.

Каков правильный путь? Сначала я использую код Entity Framework, если это имеет значение.

ответ

1

У меня есть код, пожалуйста, проверьте и попробуйте.

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); 
    } 
} 

В вышеприведенном классе UserReviewConfiguration, я сопоставляюсь следующим образом: пользователь может иметь ноль или более UserReview размещенного, UserReview размещен только одним пользователя и может быть только для одного пользователя, и отображается с одного обзором только для того, чтобы независимые ревью и пользовательские сущности были необходимы, если кому-то это нужно.

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, я сопоставляются следующим образом: пользователь может иметь ноль или более TransactionReview размещенной, TransactionReview размещена только одним пользователем и может быть только для одной транзакции, и отображается с одного обзора только для того, чтобы независимые пользователи, просмотры и транзакции были независимыми, если кому-то это нужно.

Надеюсь, что это поможет ...

1

я бы, вероятно, пойти с простой моделью данных:

  • User
  • Transaction (без сохранения информации о обзорах здесь)
  • Review (обзор должен быть либо для конкретного пользователя или a)

Вы можете отличить обзор по его типу (таблицу словаря), чтобы узнать, какой обзор является автономным nd, который поставляется с транзакцией.

Вы можете пойти двумя путями об этом:

  • есть две колонки для хранения идентификаторы Transaction и User сущности и хранение аннулирует в зависимости от типа
  • или имеющие один столбец, который будет идентифицировать идентификатор сущность по типу обзора

Я не вижу необходимости в объекте TransactionReview, так как один отзыв может быть прикреплен только к транзакции 0..1. Так как транзакции могут иметь 0..2 отзывы, это становится отношением «один ко многим» с необязательными нулевыми элементами.

Я согласен, что это может усложнить логику извлечения (необходимо помнить об этом), но я считаю это очень удобным при работе с данными, подобранными таким образом.

+0

Спасибо за это. Я знаю, что в этих случаях часто используется «Дискриминатор» - это хороший вариант для этого? – RobVious

+0

Глядя на это ... http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/implementing-inheritance-with-entity-framework-in -an-asp-net-mvc-application – RobVious

+0

Я предпочитаю эту модель, потому что ваш случай довольно прост и строг. Кроме того, продление вашего дела будет быстрее для этого типа. Если вы хотите иметь огромные таблицы, и приложение будет отделять отзывы для пользователей от транзакций для транзакций, может быть полезно использовать TPT. Мне лично нравится TPH до предела в несколько столбцов. Это зависит от вас. –

Смежные вопросы