EntityFrameworkCore - фильтр DbSet для одного свойства другого объекта - PullRequest
1 голос
/ 16 апреля 2019

У меня есть объект Account, для которого я хочу иметь свойство Subscription с именем CurrentSubscription.

public class Account
{
    public int Id { get; set; }
    public Subscription CurrentSubscription { get; set; }
}

public class Subscription
{
    public int Id { get; set; }
    public int AccountId { get; set; }
    public Account Account { get; set; }
    public DateTime Start { get; set; }
    public DateTime? End { get; set; }
}

В действительности может быть несколько Subscription строк для данной учетной записи, но бизнес-правило гласит, что когда-либо будет только одна (или ни одна) с EndDate, равным null (текущая подписка Account).В моей модели меня не волнуют другие, когда я получаю учетную запись, потому что я только после текущей .

Как я могу сказать EF сделать это?Игра с беглым API не предполагает, что в PropertyBuilder есть что-то встроенное, и каждый найденный мной пример HasDefaultValueSql имеет тривиальный Sql, как "GETDATE()", в отличие от чего-то параметризованного, что должно быть(..where AccountId = ?).

Так что я застрял ... есть идеи?

Ответы [ 2 ]

0 голосов
/ 17 апреля 2019

В действительности, для данной учетной записи может быть несколько строк подписки, но бизнес-правило предписывает, что когда-либо будет только одна (или не будет) конечная дата нуля (текущая подписка учетной записи). В моей модели меня не волнуют другие, когда я получаю учетную запись, поскольку я только после текущей. Как я могу сказать EF сделать это?

Ядро Entity Framework имеет точное решение, которое вы ищете, а именно: Взаимоотношения ядра EF: один к одному .

Итак, ваша Subscription конфигурация объекта должна быть следующей:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
     base.OnModelCreating(modelBuilder);

     modelBuilder.Entity<Subscription>().HasOne(s => s.Account)
            .WithOne(a => a.CurrentSubscription).HasForeignKey<Subscription>(s => s.AccountId);
}

Более того, поскольку для Account будет один или ноль Subscription, мы можем удалить столбец Id из сущности Subscription и сделать AccountId первичным ключом сущности Subscription следующим образом:

public class Subscription
{
    public int AccountId { get; set; }
    public Account Account { get; set; }
    public DateTime Start { get; set; }
    public DateTime? End { get; set; }
}

Тогда ваша Subscription конфигурация объекта должна быть следующей:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
     base.OnModelCreating(modelBuilder);

     modelBuilder.Entity<Subscription>(s =>
     {
        s.HasKey(sc => sc.AccountId); // <-- AccountId as primary key
        s.HasOne(sc => sc.Account).WithOne(a => a.CurrentSubscription)
                .HasForeignKey<Subscription>(sc => sc.AccountId);
     });
}
0 голосов
/ 16 апреля 2019

Это должно работать в вашем случае:

public class Account
{
    public int Id { get; set; }

    //Collection automatically loaded by EF
    public virtual List<Subscription> Subscriptions { get; set; }

    // Returns Only (or none) subscription with null End date 
    public Subscription CurrentSubscription => Subscriptions.SingleOrDefault(r=>r.End == null);
}

Account.Subscriptions -коллекция автоматически (лениво) загружается Entity Framework, если внешний ключ правильно установлен в классе подписки (или с помощью Fluent API):

public class Subscription
{
    public int Id { get; set; }
    public int AccountId { get; set; }
    [ForeignKey("AccountId")]
    public Account Account { get; set; }
    public DateTime Start { get; set; }
    public DateTime? End { get; set; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...