【问题标题】:Should I use custom setters in EF Core models?我应该在 EF Core 模型中使用自定义设置器吗?
【发布时间】:2017-11-26 13:59:32
【问题描述】:

我只是想知道是否应该在 EF Core 模型中使用自定义设置器。考虑这个非常简单的例子:

using System;

namespace EFTest.Models
{
    public class Reservation
    {
        public int ReservationId { get; set; }
        public DateTime Start { get; set; }
        public DateTime End { get; set; }
        public int ResourceId { get; set; }
        public int CustomerId { get; set; }

        public Customer Customer { get; set; }
        public Resource Resource { get; set; }
    }

    public class Resource
    {
        public int ResourceId { get; set; }
        public string Name { get; set; }
    }

    public class Customer
    {
        public int CustomerId { get; set; }
        public string Name { get; set; }
    }
}

问题是当我必须保存模型并向其中添加类的实例时,它可以很好地处理从所述添加的实例中获取外键,如下所示:

public void SaveReservation()
{
    var db = new Datebase();
    var reservation = new Reservation(){ Start = new DateTime().Now, End = new DateTime().Now.AddDays(7)};

    reservation.Resource = db.Resources.Find(2);
    reservation.Customer = db.Customers.Find(4);

    db.Reservations.Add(reservation);
    db.SaveChanges();
} 

但是如果我为客户设置外键属性,然后添加资源的实例,例如,它完全无法处理获取外键,如下所示:

public void SaveReservation()
{
    var db = new Datebase();
    var reservation = new Reservation(){ Start = new DateTime().Now, End = new DateTime().Now.AddDays(7)};

    reservation.Resource = db.Resources.Find(2);
    reservation.CustomerId = 4;

    db.Reservations.Add(reservation);
    db.SaveChanges();
}

导致 sqlite 异常 19,'未能获取外键'或类似的东西。

我能想到的唯一解决方案是自定义设置器和获取器来处理基于键设置属性,反之亦然,例如:

using System;

namespace EFTest.Models
{
    public class Reservation
    {
        public int ReservationId { get; set; }
        public DateTime Start { get; set; }
        public DateTime End { get; set; }
        public int ResourceId 
        { 
            get
            {
                if(_Resource != null)
                {
                    return _Resource.ResourceId;
                }
                else
                {
                    return 0;
                }
            } 
            set
            {
                if(_Resource != null && !_Resource.ResourceId.Equals(value))
                {
                    _Resource = null;
                }
            } 
        }
        public int CustomerId
        { 
            get
            {
                if(_Customer != null)
                {
                    return _Customer.CustomerId;
                }
                else
                {
                    return 0;
                }
            } 
            set
            {
                if(_Customer != null && !_Customer.CustomerId.Equals(value))
                {
                    _Customer = null;
                }
            } 
        }

        public Customer Customer 
        { 
            get
            {
                return _Customer;
            } 
            set
            {
                _Customer = value;
                if(value != null)
                {
                    CustomerId = _Customer.CustomerId;
                }
                else
                {
                    CustomerId = 0;
                }
            } 
        }
        private Customer _Customer { get; set; }

        public Resource Resource
        { 
            get
            {
                return _Resource;
            } 
            set
            {
                _Resource = value;
                if(value != null)
                {
                    ResourceId = _Resource.ResourceId;
                }
                else
                {
                    ResourceId = 0;
                }
            } 
        }
        private Resource _Resource { get; set; }
    }

    public class Resource
    {
        public int ResourceId { get; set; }
        public string Name { get; set; }
    }

    public class Customer
    {
        public int CustomerId { get; set; }
        public string Name { get; set; }
    }
}

但我完全不确定这是处理问题的好方法,有人可以提供一些关于它是否是处理问题的好方法的见解吗?有没有更好的?

谢谢。

【问题讨论】:

  • 代替这个难以理解的new DateTime().Now + new TimeSpan(7, 0, 0, 0),你为什么不直接使用DateTime.Now.AddDays(7)
  • 因为我脑残。我会纠正它,但这与如何完成的问题完全无关。那里的价值观只是为了提供一些背景。 :)
  • 获取外键失败?我从未见过这种异常,并且一直在使用带有 EF 的 sqlite 进行相当多的工作。确切的异常消息是什么?如果是 FK 约束,你知道为什么。但是不,您不应该在您的 BO 中使用自定义 getter 或 setter,它们应该很好地反映您的数据库架构。
  • 我似乎无法再次引发错误,所以我不能准确地说。但它是代码“sqlite错误:19外键约束失败”或类似的东西。
  • 这种类型的错误听起来像是输入的外键实际上与另一侧的任何内容都不匹配。例如,如果您将用户 id(作为外键)设置为 4,但实际上没有 PK = 4 的用户,那么您可能会收到类似的错误。如果用户 id 未设置,即 0 或 null,也会发生这种情况,因为它基本上是相同的情况:不会有具有该 PK 的用户。

标签: c# entity-framework asp.net-core entity-framework-core


【解决方案1】:

感谢 DevilSuichiro 提供了非常清晰和有用的答案:

“但是不,你不应该在你的 BO 中使用自定义的 getter 或 setter,它们应该很好地反映你的数据库架构。”

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-30
    • 1970-01-01
    • 2020-08-16
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    相关资源
    最近更新 更多