次の方法で共有


生成されたデータ オブジェクトをカスタマイズする方法 (Entity Framework)

このトピックでは、生成されたデータ クラスにカスタム メソッドを追加する方法について説明します。このトピックの例には、Adventure Works Sales Model が使用されています。この例のコードを実行するには、あらかじめプロジェクトに AdventureWorks Sales Model を追加し、Entity Framework が使用されるようにプロジェクトを構成しておく必要があります。具体的な方法については、「Entity Framework プロジェクトを手動で構成する方法」および「Entity Data Model を手動で定義する方法 (Entity Framework)」の手順を参照してください。

この例では、生成された SalesOrderHeader クラスに対するカスタムの UpdateOrderTotal メソッドを定義しています。このカスタム メソッドは、税金、運送料、およびアイテムごとの合計の現在の値に基づいて、TotalDue プロパティを更新します。このメソッドは、Entity Framework のツールによって 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());
    }
}

参照

概念

オブジェクトのカスタマイズ (Entity Framework)

その他のリソース

カスタム オブジェクトの使用 (Entity Framework タスク)