방법: 생성된 데이터 개체 사용자 지정(Entity Framework)
이 항목에서는 생성된 데이터 클래스에 사용자 지정 메서드를 추가하는 방법을 보여 줍니다. 이 항목의 예제는 Adventure Works Sales 모델을 기반으로 합니다. 이 예제의 코드를 실행하려면 프로젝트에 AdventureWorks Sales 모델을 추가하고 Entity Framework를 사용하도록 프로젝트를 구성해야 합니다. 이렇게 하려면 방법: Entity Framework 프로젝트 수동 구성 및 방법: 엔터티 데이터 모델 수동 정의(Entity Framework)의 절차를 수행합니다.
예제
이 예제에서는 생성된 SalesOrderHeader 클래스에 대한 사용자 지정 UpdateOrderTotal 메서드를 정의합니다. 이 사용자 지정 메서드는 세금, 운송료, 개별 항목 합계의 현재 값을 기반으로 TotalDue 속성을 업데이트합니다. 이 메서드는 Entity Framework 도구를 사용하여 SalesOrderHeader 클래스를 다시 생성할 때 손실되지 않도록 partial 클래스로 정의됩니다.
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 속성을 업데이트합니다. SSDL(저장소 스키마 정의 언어) 파일에서 TotalDue에 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());
}
}