Сопоставление сущностей: проблемы при ссылке двух свойств на внешний ключ - PullRequest
1 голос
/ 26 января 2020

Рассмотрим сущности Base, club и Transfer ниже:

Base:

namespace ProjetoFutBr.Domain.Entities
{
    public abstract class BaseEntity
    {
        public virtual string Name { get; set; }
    }
}

Club:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProjetoFutBr.Domain.Entities
{
    public class Club : BaseEntity
    {
        public int IdClub { get; set; }
        public int Division { get; set; }
        public List<string> Competicoes { get; set; }
        public decimal Income { get; set; }
        public string Stadium { get; set; }

    }
}

Transfer:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProjetoFutBr.Domain.Entities
{
    public class Transfer
    {
        public int TransferId { get; set; }
        public string TypeTransfer { get; set; }
        public decimal? TransferValue { get; set; }
        public DateTime TransferDate { get; set; }

        public int OriginClub { get; set; }
        public int DestinationClub { get; set; }
        public virtual Club Club { get; set; }

        public int PlayerTraded { get; set; }
        public virtual Player Player { get; set; }


    }
}

Мне нужно сделать сопоставление переноса, чтобы и свойство OriginClub, и свойство DestinationClub указывали на ClubId. Я делаю следующую конфигурацию в TransferConfiguration:

using ProjetoFutBr.Domain.Entities;
using System;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProjetoFutBr.Infra.Data.Mapping
{
    public class TransferConfiguration : EntityTypeConfiguration<Transfer>
    {
        public TransferConfiguration()
        {
            HasKey(t => t.TransferId);

            Property(t => t.TypeTransfer)
                .IsRequired();

            HasRequired(t => t.Club)
                .WithMany()
                .HasForeignKey(t => t.OriginClub);

            HasRequired(t => t.Club)
                .WithMany()
                .HasForeignKey(t => t.DestinationClub);

            HasRequired(t => t.Player)
                .WithMany()
                .HasForeignKey(t => t.PlayerTraded);

        }
    }
}

Однако, когда я обновляю базу данных, только DestinationClub помечается как ForeignKey, который указывает на ClubId, и мне нужно ClubId для быть ссылаться также. Как я могу также пометить это свойство как ForeignKey? Есть ли более элегантный способ изобразить это бизнес-правило (у трансфера есть клуб назначения и клуб-источник)?

Я приведу ниже контекстный класс и конфигурацию сущности клубов:

ClubConfiguration:

using ProjetoFutBr.Domain.Entities;
using System;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProjetoFutBr.Infra.Data.Mapping
{
    public class ClubConfiguration : EntityTypeConfiguration<Club>
    {
        public ClubConfiguration()
        {
            HasKey(c => c.IdClub);

            Property(c => c.Name)
                .IsRequired();

            Property(c => c.Division)
                .IsRequired();

        }

    }
}

ProjetoFutBr:

using ProjetoFutBr.Domain.Entities;
using ProjetoFutBr.Infra.Data.Mapping;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ProjetoFutBr.Infra.Data.Context
{
    public class ProjetoFutBrContexto : DbContext
    {
        public ProjetoFutBrContexto()
            : base("ProjetoFutBr")
        {

        }


        public DbSet<Club> Clubs { get; set; }
        public DbSet<Player> Players { get; set; }
        public DbSet<Transfer> Transfers { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {

            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
            modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

            modelBuilder.Properties()
                .Where(p => p.Name == p.ReflectedType.Name + "Id")
                .Configure(p => p.IsKey());

            modelBuilder.Configurations.Add(new ClubConfiguration());
            modelBuilder.Configurations.Add(new PlayerConfiguration());
            modelBuilder.Configurations.Add(new TransferConfiguration());

        }

    }
}

1 Ответ

2 голосов
/ 26 января 2020

У вас должно быть два свойства навигации для каждого из FK. Также я предлагаю использовать суффикс "Id" для фактических значений FK и правильные имена для свойств навигации.

public class Transfer
{
    ...
    public int OriginClubId { get; set; }
    public int DestinationClubId { get; set; }
    public virtual Club OriginClub { get; set; }
    public virtual Club DestinationClub { get; set; }
    ...
}

Тогда вы можете выполните сопоставление следующим образом

HasRequired(t => t.OriginClub)
    .WithMany()
    .HasForeignKey(t => t.OriginClubId);

HasRequired(t => t.DestinationClub)
    .WithMany()
    .HasForeignKey(t => t.DestinationClubId);

Кроме того, вы можете рассмотреть возможность создания свойств навигации на Club обратно на Transfer.

public Club
{
    ...
    ICollection<Transfer> OriginTransfers { get; set; }
    ICollection<Transfer> DestinationTransfers { get; set; }
}

Тогда сопоставление будет

HasRequired(t => t.OriginClub)
    .WithMany(c => c.OriginTransfers)
    .HasForeignKey(t => t.OriginClubId);

HasRequired(t => t.DestinationClub)
    .WithMany(c => c.DestinationTransfers)
    .HasForeignKey(t => t.DestinationClubId);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...