Entity Framework 6 Recipes 2nd Edition (9-5) Translation-> delete a disconnected Entity, entityrecipes
9-5. delete a disconnected entity
Problem
We need to delete the object retrieved from WCF.
Solution
Let's assume that we have the payment and Bill model of the entity as shown in Figure 9-5.
Figure 9-5.OnePayment and Bill Model
Our model shows the relationship between payment records and bills. In the application, we use the client to access and interact with EF data encapsulated with WC.
In our example, we use the WCF Service to delete the Payment (Payment) entity. To make it as simple as possible, create a WCF Service library and define the model:
1. Right-click solution, select a new project, select the WCF workflow WCF Service library, and name it Recipe5.
2. right-click Recipe5 project principal to add principal new item, and select "data" ADO. NET object data model. add the Invoice and Payment tables according to the wizard. for simplicity, we have deleted the Invoice object's navigation attribute Payments (right-click on the Payments attribute of the Invoice object and select "delete from model") and right-click the TimeStamp attribute of the Payment object, select "attribute" and set "concurrency mode" to Fixed. in this way, TimeStamp is used as concurrency control. when an object is deleted or updated, its value is used as part of the Where condition of the SQL statement. use the code in Listing 9-27 to change the service definition in the IService1.cs file.
Listing 9-27.The Service Contract for Our WCF Service
[ServiceContract]
Public interface IService1
{
[OperationContract]
Payment InsertPayment ();
[OperationContract]
Void DeletePayment (Payment payment );
}
4. Implement the service in the Service1.cs file, as shown in Listing 9-28.
Listing 9-28.The Implementation of Our Service Contract
Public class Service1: IService1
{
Public Payment InsertPayment ()
{
Using (var context = new EFRecipesEntities ())
{
// Delete the previous test data
Context. Database. ExecuteSqlCommand ("delete from chapter9.payment ");
Context. Database. ExecuteSqlCommand ("delete from chapter9.invoice ");
Var payment = new Payment
{
Amount = 99.95 m,
Invoice = new Invoice {Description = "Auto Repair "}
};
Context. Payments. Add (payment );
Context. SaveChanges ();
Return payment;
}
}
Public void DeletePayment (Payment payment)
{
Using (var context = new EFRecipesEntities ())
{
Context. Entry (payment). State = EntityState. Deleted;
Context. SaveChanges ();
}
}
}
5. For the test service, a client is required. Add a new console application project to the solution.
The client code is shown in Listing 9-29. Right-click on WCF, debug idea to start a new instance, right-click idea on the console project, add idea service reference, and add reference to WCF.
Listing 9-29.A Simple Console Application to Test Our WCF Service
Class Program
{
Static void Main (string [] args)
{
Var client = new ServiceReference1.Service1Client ();
Var payment = client. InsertPayment ();
Client. DeletePayment (payment );
}
}
If you set a breakpoint before the first line of code in the Main () method, debug the breakpoint, and execute the statement by statement, you can see the execution of the WCF Service.
How it works
In this section, we demonstrate how the client calls a service to perform operations on disconnected entities.
On the client side, we use the InsertPayment () method to insert a new payment to the database. This method returns the inserted
Payment. Of course, after the payment is returned to the client, the connection will be disconnected from DbContext. In fact, DbContext can be in different processes, even on different computers,
We use DeletePayment () to delete the Payment in the database. in this method (see Listing 9-28), we call the DbContext Entry () method and pass a Payment parameter. set the property of the Payment object to EntityState. deleted, and then the SaveChanges () method will generate a Deleted SQL statement and delete the data from the database. because we use foreign key Association, The concurrency attribute TimeStamp is required and EF will be used in the SQL Where clause.
This method is used to solve the problem. you may encounter a problem. When your POCO class has one or more compound attributes, because of the composite type, it is important in EF and cannot be null, the simple solution is to create a virtual instance for the composite type. If you set the composite type to null, The SaveChanges () method throws an exception.
If multiple to 1 and 0 .. 1. EF requires that their object keys have correct values to generate a Where clause for modification and deletion. in our example, if there is an independent association between Invoice and Payment, we need to set the correct value for the InvoiceId navigation of Invoice to associate the Invoice instance. in this way, the Where clause will contain PaymentId, TimeStamp, and InvoiceId.
========================================================== ======================================
■Note: When UsingEFOne instanceNIn layer architecture, we should carefully consider whether to use the foreign key allocation to associate related entities,Independent Association is difficult to implement and will complicate your code.. This is the release of Arthur Vickers from EF team.Whats-the-deal-with-mapping-foreign-keys-using-the-entity-frameworkBlog, there is a good explanation. Of course you are also welcome to read his EF other articles.
========================================================== ====================================
If entity objects contain multiple independent associations, setting them is boring. You can simply retrieve them from the database and then delete them, which makes your code simpler, however, when you retrieve the data from the database, EF will rewrite the relationships between these entities.
Of course you can haveNoTrackingOption to disable context tracing.
If we use an independent association method in this section to delete a flag for a Payment object that has been loaded, EF will delete the flag for the Payment and associated Invoice.
Similarly, the Where clause of the SQL statement contains the PaymentId, TimeStamp, and InvoiceId columns.
Another option for deleting an object from an independent association is to pre-load the associated object, and then pass the entire object graph to the WCF or Web API for deletion. For our instance, we can pre-load the Invoice and related Payment entities. To delete a Payment object, we need to return the entire object containing the Invoice object to the service. However, this will consume more bandwidth and have more processing time in sequence, so the benefits it may bring are not as good as the consumption.
Appendix: script file of the database used in the Creation example