如何:自定义生成的数据对象(实体框架)

本主题介绍如何将自定义方法添加到生成的数据类中。本主题中的示例基于 Adventure Works 销售模型。若要运行本示例中的代码,必须已将 AdventureWorks 销售模型添加到您的项目中,并将项目配置为使用实体框架。为此,请完成如何:手动配置实体框架项目如何:手动定义实体数据模型(实体框架) 中的过程。

示例

此示例为生成的 SalesOrderHeader 类定义自定义方法 UpdateOrderTotal。此自定义方法根据税费、运费及各项总计的当前值更新 TotalDue 属性。此方法将定义为分部类,以便在实体框架工具重新生成 SalesOrderHeader 类时不会丢失。

Partial Public Class SalesOrderHeader
    ' Update the order total.
    Public Sub UpdateOrderTotal()

        Dim newSubTotal As Decimal = 0

        ' Ideally, this information is available in the EDM.
        Dim taxRatePercent As Decimal = GetCurrentTaxRate()
        Dim freightPercent As Decimal = GetCurrentFreight()

        ' If the items for this order are loaded or if the order is 
        ' newly added, then recalculate the subtotal as it may have changed.
        If (Me.SalesOrderDetail.IsLoaded Or _
            Me.EntityState = Data.EntityState.Added) Then

            Dim item As SalesOrderDetail
            For Each item In Me.SalesOrderDetail
                ' Calculate line totals for loaded items.
                newSubTotal += (item.OrderQty * _
                    (item.UnitPrice - item.UnitPriceDiscount))
            Next
            Me.SubTotal = newSubTotal
        End If

        ' Calculate the new tax amount.
        Me.TaxAmt = Me.SubTotal _
             + Decimal.Round((Me.SubTotal * taxRatePercent / 100), 4)

        ' Calculate the new freight amount.
        Me.Freight = Me.SubTotal _
            + Decimal.Round((Me.SubTotal * freightPercent / 100), 4)

        ' Calculate the new total.
        Me.TotalDue = Me.SubTotal + Me.TaxAmt + Me.Freight

    End Sub
End Class
public partial class SalesOrderHeader
{
    // Update the order total.
    public void UpdateOrderTotal()
    {
        decimal newSubTotal = 0;

        // Ideally, this information is available in the EDM.
        decimal taxRatePercent = GetCurrentTaxRate();
        decimal freightPercent = GetCurrentFreight();

        // If the items for this order are loaded or if the order is 
        // newly added, then recalculate the subtotal as it may have changed.
        if (SalesOrderDetail.IsLoaded ||
            EntityState == EntityState.Added)
        {
            foreach (SalesOrderDetail item in this.SalesOrderDetail)
            {
                // Calculate line totals for loaded items.
                newSubTotal += (item.OrderQty *
                    (item.UnitPrice - item.UnitPriceDiscount));
            }

            this.SubTotal = newSubTotal;
        }

        // Calculate the new tax amount.
        this.TaxAmt = this.SubTotal
             + Decimal.Round((this.SubTotal * taxRatePercent / 100), 4);

        // Calculate the new freight amount.
        this.Freight = this.SubTotal
            + Decimal.Round((this.SubTotal * freightPercent / 100), 4);

        // Calculate the new total.
        this.TotalDue = this.SubTotal + this.TaxAmt + this.Freight;
    }
}

此示例修改某一订单,然后对 SalesOrderHeader 调用自定义方法 UpdateOrderTotal 以更新 TotalDue 属性。因为 TotalDue 具有应用在存储架构定义语言 (SSDL) 文件中的 StoreGeneratedPattern="computed" 属性,所以调用 SaveChanges 时,不会将此更新后的值保存到服务器。如果没有此属性,则在尝试在服务器上更新计算列时会发生 UpdateException

Dim orderId As Integer = 43662

Using context As New AdventureWorksEntities
    Try
        ' Return an order and its items.
        Dim order As SalesOrderHeader = _
        context.SalesOrderHeader() _
        .Include("SalesOrderDetail") _
        .Where("it.SalesOrderID = @orderId", _
               New ObjectParameter("orderId", orderId)).First()

        Console.WriteLine("The original order total was: " _
            + order.TotalDue.ToString())

        ' Update the order status.
        order.Status = 1

        ' Increase the quantity of the first item, if one exists.
        If order.SalesOrderDetail.Count > 0 Then
            order.SalesOrderDetail.First().OrderQty += Convert.ToInt16(1)
        End If
        ' Increase the shipping amount by 10%.
        order.Freight = _
            Decimal.Round(order.Freight * Convert.ToDecimal(1.1), 4)

        ' Call the custom method to update the total.
        order.UpdateOrderTotal()

        Console.WriteLine("The calculated order total is: " _
            + order.TotalDue.ToString())

        ' Save changes in the object context to the database.
        Dim changes As Integer = context.SaveChanges()

        ' Refresh the order to get the computed total from the store.
        context.Refresh(RefreshMode.StoreWins, order)

        Console.WriteLine("The store generated order total is: " _
            + order.TotalDue.ToString())
    Catch ex As InvalidOperationException
        Console.WriteLine(ex.ToString())
    Catch ex As UpdateException
        Console.WriteLine(ex.ToString())
    End Try
End Using
int orderId = 43662;

using (AdventureWorksEntities context =
    new AdventureWorksEntities())
{
    try
    {
        // Return an order and its items.
        SalesOrderHeader order =
            context.SalesOrderHeader
            .Include("SalesOrderDetail")
            .Where("it.SalesOrderID = @orderId", 
               new ObjectParameter("orderId", orderId)).First();

        Console.WriteLine("The original order total was: "
            + order.TotalDue);

        // Update the order status.
        order.Status = 1;

        // Increase the quantity of the first item, if one exists.
        if (order.SalesOrderDetail.Count > 0)
        {
            order.SalesOrderDetail.First().OrderQty += 1;
        }

        // Increase the shipping amount by 10%.
        order.Freight = 
            Decimal.Round(order.Freight * (decimal)1.1, 4);

        // Call the custom method to update the total.
        order.UpdateOrderTotal();
        
        Console.WriteLine("The calculated order total is: "
            + order.TotalDue);

        // Save changes in the object context to the database.
        int changes = context.SaveChanges();

        // Refresh the order to get the computed total from the store.
        context.Refresh(RefreshMode.StoreWins, order);

        Console.WriteLine("The store generated order total is: "
            + order.TotalDue);
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine(ex.ToString());
    }
    catch (UpdateException ex)
    {
        Console.WriteLine(ex.GetType().ToString() +": " + ex.ToString());
    }
}

另请参见

概念

自定义对象(实体框架)

其他资源

使用自定义对象(实体框架任务)