linq - 在CF实体类中,EF CodeFirst计算

  显示原文与译文双语对照的内容

我已经将计算字段( ActiveCreditsLeft ) 直接添加到CodeFirst实体类。 在CF实体类中添加计算字段逻辑是好主意?


 public class User : Entity
 {
 public User()
 {
 Id = Helper.GetRandomInt(9);
 DateStamp = DateTime.UtcNow;
 TimeZone = TimeZoneInfo.Utc.Id;
 }

 [DatabaseGenerated(DatabaseGeneratedOption.None)]
 public int Id { get; set; } 
 [Required]
 [MaxLength(50)]
 public string Email { get; set; }
 [Required]
 [MaxLength(50)]
 public string Password { get; set; }
 [MaxLength(50)]
 public string FirstName { get; set; }
 [MaxLength(50)]
 public string LastName { get; set; }
 [Required]
 public DateTime DateStamp { get; set; } 

 public virtual ICollection<Order> Orders { get; set; }
 public virtual ICollection<Statistic> Statistics { get; set; }
 public virtual ICollection<Notification> Notifications { get; set; }


 [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
 public bool Active
 {
 get
 {
 return Orders.Any(c => c.Active && (c.TransactionType == TransactionType.Order || c.TransactionType == TransactionType.Subscription));
 }
 }

 [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
 public int CreditsLeft
 {
 get
 {
 return Orders.Sum(p => p.Credits!= null? p.Credits.Value : 0);
 }
 }

 }

时间: 作者:

在CF实体类中添加计算字段逻辑是好主意?

当然,你可以这样做,但是有一些事情你必须处理。

首先,由业务逻辑计算的属性的属性不是 [DatabaseGenerated(DatabaseGeneratedOption.Computed)] ,因为这表明值是在数据库( 与计算列中一样) 中计算的。 你应该用 [NotMapped] 属性标记该属性。 这将告诉 Entity Framework 忽略数据库映射中的属性。

第二,由于两个属性都使用 Orders,因这里必须确保在访问任何属性时加载订单或者可以延迟加载。 因此,你可能希望使用 Include 语句( Include(user => user.Orders) ) 加载 User 。 否则,你必须确保在访问 Active 或者 CreditsLeft 时上下文仍然处于活动状态。

另外,你不能在有效的LINQ查询中直接处理属性,如下所示


db.Users.Select(u => u.Active);

因为EF会抛出一个不知道 Active的异常。 你只能在内存中的物化用户对象上处理属性。

作者:
...