I have an Account
entity, on which I want to have a Subscription
property called 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; }
}
In reality, there could be multiple Subscription
rows for a given account but a business rule dictates that there will only ever be one (or none) with an EndDate
of null
(the Account
's current subscription). In my model I do not care about the others when I am retrieving an account as I am only after the current one.
How can I tell EF to do this? Playing around with the fluent API doesn't suggest there is anything built in on PropertyBuilder
and every example of HasDefaultValueSql
I have found has trivial Sql
like "GETDATE()"
as opposed to something parameterised, which this would need to be ( ..where AccountId = ?
).
So I'm stuck.. any ideas?
This should work in your case:
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
-collection is automatically (lazy) loaded by Entity Framework if foreign key is proper set on Subscription class (or by 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; }
}
In reality, there could be multiple Subscription rows for a given account but a business rule dictates that there will only ever be one (or none) with an EndDate of null (the Account's current subscription). In my model I do not care about the others when I am retrieving an account as I am only after the current one. How can I tell EF to do this?
Entity Framework Core has exact solution that you are searching for and that is EF Core Relationships : One-to-One .
So your Subscription
entity configuration should be as follows:
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);
}
Moreover as there will be one or zero Subscription
for Account
so we can remove Id
column from Subscription
entity and make the AccountId
as the primary key of the Subscription
entity as follows:
public class Subscription
{
public int AccountId { get; set; }
public Account Account { get; set; }
public DateTime Start { get; set; }
public DateTime? End { get; set; }
}
Then your Subscription
entity configuration should be as follows:
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);
});
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.