延迟加载时订阅EntitySet项中的事件 [英] Subscribing to Events in EntitySet Items when Lazy Loading

查看:56
本文介绍了延迟加载时订阅EntitySet项中的事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用LINQ to SQL并遇到一个问题,当EntitySet加载时,没有通知它已加载,也没有在从SQL添加项目时调用Item Added操作委托。



我想要做的是让PurchaseOrder在PurchaseOrderDetail触发PropertyChanged事件时重新计算其属性。



以下是完整的PurchaseOrder类。我很感激任何建议。



I am using LINQ to SQL and have run into a problem that when an EntitySet loads there is no notification that it has loaded, nor does it call the Item Added action delegate when it adds the items from SQL.

What I am trying to do is have a PurchaseOrder recalculate its properties when a PurchaseOrderDetail fires the PropertyChanged Event.

Below is the PurchaseOrder Class in its entirety. I would appreciate any suggestions.

[Table(Name = "PurchaseOrder")]
public class PurchaseOrder : INotifyPropertyChanged
{
    private readonly EntitySet<PurchaseOrderDetail> _details;
    private readonly EntitySet<POReceiptLog> _log;
    private EntityRef<Company> _supplier;
    private string _contact;
    private bool _closed;
    private decimal _grandTotal;
    private decimal _tax;
    private decimal _totalPrice;
    private string _terms;
    private string _carrier;
    private string _shipToAddress;
    private string _notes;
    private DateTime _requiredDate;
    private DateTime _date;
    private string _supplierName;
    private int _supplierID;
    private int _id;

    /// <summary>
    /// Initializes a new instance of the <see cref="PurchaseOrder"/> class.
    /// </summary>
    public PurchaseOrder()
    {
        _details = new EntitySet<PurchaseOrderDetail>(AttachDetail, DetachDetail);
        _details.ListChanged += DetailsListChanged;
        _log = new EntitySet<POReceiptLog>(AttachLog, DetachLog);

    }

    void DetailsListChanged(object sender, ListChangedEventArgs e)
    {
        if (e.ListChangedType == ListChangedType.ItemAdded)
        {
            _details.ElementAt(e.NewIndex).PropertyChanged += ObjPropertyChanged;
        }
        UpdateCalculatedFields();
    }

    /// <summary>
    /// Gets or sets the contact.
    /// </summary>
    /// <value>The contact.</value>
    [Column]
    public String Contact
    {
        get { return _contact; }
        set
        {
            if (value == _contact) return;
            _contact = value;
            OnPropertyChanged("Contact");
        }
    }

    /// <summary>
    /// Gets or sets the ID.
    /// </summary>
    /// <value>The ID.</value>
    [Column(IsPrimaryKey = true, IsDbGenerated = true)]
    public int ID
    {
        get { return _id; }
        set
        {
            if (value == _id) return;
            _id = value;
            OnPropertyChanged("ID");
        }
    }

    /// <summary>
    /// Gets or sets the supplier ID.
    /// </summary>
    /// <value>The supplier ID.</value>
    [Column(Name = "Supplier")]
    public int SupplierID
    {
        get { return _supplierID; }
        set
        {
            if (value == _supplierID) return;
            _supplierID = value;
            OnPropertyChanged("SupplierID");
        }
    }

    /// <summary>
    /// Gets or sets the name of the supplier.
    /// </summary>
    /// <value>The name of the supplier.</value>
    [Column]
    public string SupplierName
    {
        get { return _supplierName; }
        set
        {
            if (value == _supplierName) return;
            _supplierName = value;
            OnPropertyChanged("SupplierName");
        }
    }

    /// <summary>
    /// Gets or sets the date.
    /// </summary>
    /// <value>The date.</value>
    [Column(Name = "CreatedOn")]
    public DateTime Date
    {
        get { return _date; }
        set
        {
            if (value.Equals(_date)) return;
            _date = value;
            OnPropertyChanged("Date");
        }
    }

    /// <summary>
    /// Gets or sets the required date.
    /// </summary>
    /// <value>The required date.</value>
    [Column(Name = "RequiredBy")]
    public DateTime RequiredDate
    {
        get { return _requiredDate; }
        set
        {
            if (value.Equals(_requiredDate)) return;
            _requiredDate = value;
            OnPropertyChanged("RequiredDate");
        }
    }

    /// <summary>
    /// Gets or sets the notes.
    /// </summary>
    /// <value>The notes.</value>
    [Column]
    public string Notes
    {
        get { return _notes; }
        set
        {
            if (value == _notes) return;
            _notes = value;
            OnPropertyChanged("Notes");
        }
    }

    /// <summary>
    /// Gets or sets the ship to address.
    /// </summary>
    /// <value>The ship to address.</value>
    [Column(Name = "ShipTo")]
    public string ShipToAddress
    {
        get { return _shipToAddress; }
        set
        {
            if (value == _shipToAddress) return;
            _shipToAddress = value;
            OnPropertyChanged("ShipToAddress");
        }
    }

    /// <summary>
    /// Gets or sets the carrier.
    /// </summary>
    /// <value>The carrier.</value>
    [Column(Name = "ShipVia")]
    public string Carrier
    {
        get { return _carrier; }
        set
        {
            if (value == _carrier) return;
            _carrier = value;
            OnPropertyChanged("Carrier");
        }
    }

    /// <summary>
    /// Gets or sets the terms.
    /// </summary>
    /// <value>The terms.</value>
    [Column]
    public string Terms
    {
        get { return _terms; }
        set
        {
            if (value == _terms) return;
            _terms = value;
            OnPropertyChanged("Terms");
        }
    }

    /// <summary>
    /// Gets or sets the total price.
    /// </summary>
    /// <value>The total price.</value>
    [Column(Name = "Price")]
    public decimal TotalPrice
    {
        get { return _totalPrice; }
        set
        {
            if (value == _totalPrice) return;
            _totalPrice = value;
            OnPropertyChanged("TotalPrice");
        }
    }

    /// <summary>
    /// Gets or sets the tax.
    /// </summary>
    /// <value>The tax.</value>
    [Column]
    public decimal Tax
    {
        get { return _tax; }
        set
        {
            if (value == _tax) return;
            _tax = value;
            OnPropertyChanged("Tax");
        }
    }

    /// <summary>
    /// Gets or sets the grand total.
    /// </summary>
    /// <value>The grand total.</value>
    [Column(Name = "Total")]
    public decimal GrandTotal
    {
        get { return _grandTotal; }
        set
        {
            if (value == _grandTotal) return;
            _grandTotal = value;
            OnPropertyChanged("GrandTotal");
        }
    }

    /// <summary>
    /// Gets or sets a value indicating whether this <see cref="PurchaseOrder"/> is closed.
    /// </summary>
    /// <value><c>true</c> if closed; otherwise, <c>false</c>.</value>
    [Column(UpdateCheck = UpdateCheck.Never)]
    public bool Closed
    {
        get { return _closed; }
        set
        {
            if (value.Equals(_closed)) return;
            _closed = value;
            OnPropertyChanged("Closed");
        }
    }

    /// <summary>
    /// Gets or sets the details.
    /// </summary>
    /// <value>The details.</value>
    [Association(Storage = "_details", ThisKey = "ID", OtherKey = "PurchaseOrderID")]
    public ICollection<PurchaseOrderDetail> Details
    {
        get { return _details; }
        set { _details.Assign(value); }
    }

    /// <summary>
    /// Gets or sets the receive log.
    /// </summary>
    /// <value>The receive log.</value>
    [Association(Storage = "_log", ThisKey = "ID", OtherKey = "PurchaseOrderID")]
    public ICollection<POReceiptLog> RecieveLog
    {
        get { return _log; }
        set { _log.Assign(value); }
    }

    /// <summary>
    /// Gets or sets the supplier.
    /// </summary>
    /// <value>The supplier.</value>
    [Association(Storage = "_supplier", ThisKey = "SupplierID", OtherKey = "ID", IsForeignKey = true)]
    public Company Supplier
    {
        get { return _supplier.Entity; }
        set { _supplier.Entity = value; }
    }

    private void AttachDetail(PurchaseOrderDetail obj)
    {
        obj.PO = this;
        obj.PropertyChanged += ObjPropertyChanged;
    }

    void ObjPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        UpdateCalculatedFields();
    }

    private void UpdateCalculatedFields()
    {
        TotalPrice = Details.Sum(d => d.ExtendedPrice);
        if (_supplier.Entity != null && _supplier.Entity.ArDetails != null)
            Tax = TotalPrice*(_supplier.Entity.ArDetails.Tax/100);
        GrandTotal = TotalPrice + Tax;
        Closed = Details.All(d => d.Closed);
    }

    private void DetachDetail(PurchaseOrderDetail obj)
    {
        obj.PropertyChanged -= ObjPropertyChanged;
        obj.PO = null;
    }

    private void AttachLog(POReceiptLog obj)
    {
        obj.PurchaseOrder = this;
    }

    private void DetachLog(POReceiptLog obj)
    {
        obj.PurchaseOrder = null;
    }

    /// <summary>
    /// Occurs when a property value changes.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    private void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

推荐答案

Okay here is a workaround have found. I don’’t know how elegant it is but it works.

Okay here is a workaround have found. I don''t know how elegant it is but it works.
public ICollection<PurchaseOrderDetail> Details
        {
            get {
                if (!_details.HasLoadedOrAssignedValues)
                {
                    _details.Load();
                    foreach (var purchaseOrderDetail in _details)
                    {
                        AttachDetail(purchaseOrderDetail);
                        UpdateCalculatedFields();
                    }
                }
                return _details;
                }
            set { _details.Assign(value); }
        }



When the association tries to lazy load the EntitySet<t> it does not use the Setter when a storage property is set and will not load when it is not set. In the getter you can force the loading and do what you need to do on the initial load.



If anyone has a better solution I would love to hear it.


When the association tries to lazy load the EntitySet<t> it does not use the Setter when a storage property is set and will not load when it is not set. In the getter you can force the loading and do what you need to do on the initial load.

If anyone has a better solution I would love to hear it.


这篇关于延迟加载时订阅EntitySet项中的事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆