Tutorial: asignar una entidad a procedimientos almacenados
En este tema se muestra cómo utilizar ADO.NET Entity Data Model Designer (Entity Designer) para asignar las operaciones de inserción, actualización y eliminación de un tipo de entidad a procedimientos almacenados. Las operaciones de inserción, actualización y eliminación de un tipo de entidad pueden utilizar las instrucciones SQL que genera el sistema automáticamente (de forma predeterminada) o pueden utilizar los procedimientos almacenados que especifique el programador. El código de aplicación que se emplea para crear, actualizar y eliminar las entidades es el mismo tanto si se utilizan procedimientos almacenados para actualizar la base de datos como si no.
En este tutorial, asignará dos tipos de entidad a procedimientos almacenados modificando el Entity Data Model (EDM) utilizado en la aplicación CourseManager (para obtener más información, consulte la sección Requisitos previos, posteriormente en este tema). También escribirá código que insertará, actualizará y eliminará los tipos de entidad.
Requisitos previos
Para completar este tutorial, debe generar la aplicación CourseManager. Para obtener más información e instrucciones, vea el Tutorial rápido de Entity Framework. Después de generar esta aplicación, modificará su EDM asignando dos tipos de entidad a los procedimientos almacenados.
Nota |
---|
Dado que muchos de los temas del tutorial de esta documentación usan la aplicación CourseManager como punto de partida, recomendamos que utilice una copia de la misma, en lugar de modificar el código original. |
Este tutorial supone que el lector tiene conocimientos básicos de Visual Studio, .NET Framework y sobre la programación en Visual C# o Visual Basic.
Asignar la entidad Person a procedimientos almacenados
Al asignar la operación de inserción de una entidad a un procedimiento almacenado, si el servidor crea el valor de clave principal para la fila insertada, debe asignar de nuevo este valor a la propiedad de clave de la entidad. En este ejemplo, el procedimiento almacenado InsertPerson devuelve la clave principal creada recientemente como parte del conjunto de resultados del procedimiento almacenado. La clave principal se asigna a la clave de entidad (PersonID) utilizando la característica <Agregar Result Binding> de Entity Designer.
Para asignar la entidad Person a procedimientos almacenados
Abra la solución CourseManager en Visual Studio.
En el Explorador de soluciones, haga doble clic en el archivo School.edmx.
El archivo School.edmx se abre en ADO.NET Entity Data Model Designer (Entity Designer).
Haga clic con el botón secundario en el tipo de entidad Person y seleccione Asignación de procedimientos almacenados.
Las asignaciones de procedimientos almacenados aparecen en la ventana Detalles de la asignación.
Haga clic en <Seleccionar Insert Function>.
El campo se convierte en una lista desplegable de los procedimientos almacenados incluidos en el EDM.
En la lista desplegable, seleccione InsertPerson.
Aparecen las asignaciones predeterminadas entre los parámetros de procedimiento almacenado y las propiedades de entidad. Observe que las flechas indican la dirección de la asignación: se proporcionan valores de propiedad como parámetros de procedimiento almacenado.
Haga clic en <Agregar Result Binding>.
El campo se puede modificar.
Reemplace <Agregar Result Binding> con NewPersonID, el nombre del parámetro que devuelve el procedimiento almacenado InsertPerson. Presione Entrar.
De forma predeterminada, NewPersonID se asigna a la clave de entidad PersonID. Observe que una flecha indica la dirección de la asignación: el valor de la columna de resultado se proporciona para la propiedad.
Haga clic en <Seleccionar Update Function> y seleccione UpdatePerson en la lista desplegable resultante.
Aparecen las asignaciones predeterminadas entre los parámetros de procedimiento almacenado y las propiedades de entidad.
Haga clic en <Seleccionar Delete Function> y seleccione DeletePerson en la lista desplegable resultante.
Aparecen las asignaciones predeterminadas entre los parámetros de procedimiento almacenado y las propiedades de entidad.
Las operaciones de inserción, actualización y eliminación de un tipo de entidad Person están asignadas ahora a procedimientos almacenados.
Asignar la entidad OfficeAssignment a procedimientos almacenados
Si el tipo de entidad en un extremo de una asociación uno a uno está asignado a los procedimientos almacenados, la entidad en el otro extremo de la asociación también debe estar asignada a los procedimientos almacenados. En este ejemplo, se asigna el tipo de entidad OfficeAssignment a los procedimientos almacenados porque tiene una asociación uno a uno con el tipo de entidad Person. En esta asignación se utiliza la opción Usar Original Value en la operación de actualización para habilitar una manera cómoda de comprobar la simultaneidad en el código de aplicación.
Para asignar la entidad OfficeAssignment a procedimientos almacenados
Haga clic con el botón secundario en el tipo de entidad OfficeAssignment y seleccione Stored Procedure Mapping.
Las asignaciones de procedimientos almacenados aparecen en la ventana Detalles de la asignación.
Haga clic en <Seleccionar Insert Function> y seleccione InsertOfficeAssignment en la lista desplegable resultante.
Aparecen las asignaciones predeterminadas entre los parámetros de procedimiento almacenado y las propiedades de entidad.
Haga clic en <Agregar Result Binding>.
El campo se puede modificar.
Escriba Timestamp en lugar de <Agregar Result Binding>.
Haga clic en el campo vacío en la columna Propery/Value junto a Timestamp.
El campo se convierte en una lista desplegable de propiedades a las que podemos asignar el valor que devuelve el procedimiento almacenado InsertOfficeAssignment.
En la lista desplegable, seleccione Timestamp.
Haga clic en <Seleccionar Update Function> y seleccione UpdateOfficeAssignment en la lista desplegable resultante.
Aparecen las asignaciones predeterminadas entre los parámetros de procedimiento almacenado y las propiedades de entidad. Las casillas de verificación aparecen en la columna Usar Original Value al lado de cada propiedad asignada.
Haga clic en el campo vacío en la columna Propiedad que corresponda al parámetro OrigTimestamp y seleccione Timestamp en la lista desplegable resultante.
Entity Designer no realizó la asignación predeterminada porque el nombre de parámetro no coincidía exactamente con el nombre de propiedad.
Active el cuadro de la columna Usar Original Value que corresponda a la propiedad Timestamp.
Cuando se intenta una actualización, se usa el valor de la propiedad Timestamp que se leyó originalmente de la base de datos al volver a escribir los datos en la base de datos. Si el valor no coincide con el de la base de datos, se iniciará una OptimisticConcurrencyException.
Haga clic en <Agregar Result Binding>.
El campo se puede modificar.
Reemplace <Agregar Result Binding> con Timestamp.
Haga clic en el campo vacío en la columna Propery/Value junto a Timestamp.
El campo se convierte en una lista desplegable de propiedades a las que podemos asignar la columna de resultados que devuelve el procedimiento almacenado UpdateOfficeAssignment.
En la lista desplegable, seleccione Timestamp.
Haga clic en <Seleccionar Delete Function> y seleccione DeleteOfficeAssignment en la lista desplegable resultante.
Aparecen las asignaciones predeterminadas entre los parámetros de procedimiento almacenado y las propiedades de entidad.
Las operaciones de inserción, actualización y eliminación de un tipo de entidad OfficeAssignment están asignadas ahora a procedimientos almacenados.
Construir la interfaz de usuario
A continuación, agregará dos formularios a la aplicación CourseManager. Un formulario proporciona una interfaz para ver y actualizar la información de instructor. El otro formulario proporciona una interfaz para ver y actualizar las asignaciones de la oficina.
Para construir la interfaz de usuario
Haga clic con el botón secundario en el proyecto CourseManager en el Explorador de soluciones, seleccione Agregar y seleccione Nuevo elemento.
Aparecerá el cuadro de diálogo Agregar nuevo elemento.
Seleccione Windows Forms, establezca el nombre del formulario en InstructorViewer.vb o InstructorViewer.cs, y haga clic en Agregar.
Se agrega un formulario nuevo al proyecto y se abre en el diseñador de formularios. El nombre del formulario se establece en InstructorViewer y el texto en InstructorViewer.
Arrastre un control DataGridView del cuadro de herramientas al formulario y establezca su Nombre en instructorGridView en la ventana Propiedades.
Arrastre un control Button del cuadro de herramientas al formulario. Establezca su Nombre en updateInstructor y su Texto en Update Instructor.
Arrastre otro control Button del cuadro de herramientas al formulario. Establezca su Nombre en viewOffices y su Texto en View Offices.
Haga clic con el botón secundario en el proyecto CourseManager en el Explorador de soluciones, seleccione Agregar y seleccione Nuevo elemento.
Aparecerá el cuadro de diálogo Agregar nuevo elemento.
Seleccione Windows Forms, establezca el nombre del formulario en OfficeViewer.vb u OfficeViewer.cs, y haga clic en Agregar.
Se agrega un formulario nuevo al proyecto y se abre en el diseñador de formularios. El nombre del formulario se establece en OfficeViewer y el texto en OfficeViewer.
Arrastre un control ComboBox del cuadro de herramientas al formulario y establezca su Nombre en instructorList.
Arrastre un control TextBox del cuadro de herramientas al formulario y establezca su Nombre en officeLocation.
Arrastre un control Button del cuadro de herramientas al formulario. Establezca el valor de Nombre en updateOffice y el de Texto en Update Office.
En el Explorador de soluciones, haga doble clic en el formulario CourseViewer.vb o CourseViewer.cs.
La vista de diseño del formulario CourseViewer aparece.
Arrastre un control Button del cuadro de herramientas al formulario.
En la ventana Propiedades, establezca la propiedad Name de Button en viewInstructors y establezca la propiedad Text en View Instructors.
Haga doble clic en el control viewInstructorsButton.
Se abre el archivo de código subyacente para el formulario CourseViewer.
Agregue el código siguiente al controlador de eventos viewInstructors_Click:
Dim instructorViewer As New InstructorViewer() instructorViewer.Visible = True
InstructorViewer instructorViewer = new InstructorViewer(); instructorViewer.Visible = true;
Vuelva a la vista de diseño del formulario InstructorViewer.
Haga doble clic en el control viewOfficesButton.
El archivo de código subyacente para el formulario Form2 se abre.
Agregue el código siguiente al controlador de eventos viewOffices_Click:
Dim officeViewer As New OfficeViewer() officeViewer.Visible = True
OfficeViewer officeViewer = new OfficeViewer(); officeViewer.Visible = true;
La interfaz de usuario está completa ahora.
Ver y actualizar información del instructor
En este procedimiento, agregará código al formulario InstructorViewer que le permita ver y actualizar la información del instructor. Más específicamente, el código hace lo siguiente:
Enlaza DataGridView a una consulta que devuelve información sobre los tipos Person que son instructores. Para obtener más información sobre cómo enlazar objetos a controles, vea Enlazar objetos a controles (Entity Framework).
Guarda cualquier cambio (inserciones, actualizaciones o eliminaciones) en el control DataGridView en la base de datos.
Utiliza los procedimientos almacenados que asignamos anteriormente para escribir los datos en la base de datos al llamar a SaveChanges() en el controlador de eventos updateInstructor_Click.
Para ver y actualizar información del instructor
Con el formulario InstructorViewer abierto en el diseñador de formularios, haga doble clic en el formulario InstructorViewer.
El archivo de código subyacente para el formulario InstructorViewer se abre.
Agregue las instrucciones using (C#) o Imports (Visual Basic) siguientes:
Imports System.Data.Objects Imports System.Data.Objects.DataClasses
using System.Data.Objects; using System.Data.Objects.DataClasses;
Agregue una propiedad a la clase InstructorViewer que representa el contexto del objeto:
' Create an ObjectContext instance based on SchoolEntity. Private schoolContext As SchoolEntities
// Create an ObjectContext instance based on SchoolEntity. private SchoolEntities schoolContext;
En el controlador de eventos InstructorViewer_Load, agregue el código para inicializar el contexto del objeto y establecer el origen de datos para el control DataGridView en una consulta que devuelve todos los tipos Person que no tienen null en HireDate.
' Initialize the ObjectContext. schoolContext = New SchoolEntities() Dim instructorQuery As ObjectQuery(Of Person) = _ schoolContext.Person.Include("OfficeAssignment") _ .Where("it.HireDate is not null") _ .OrderBy("it.LastName") instructorGridView.DataSource = instructorQuery _ .Execute(MergeOption.OverwriteChanges) instructorGridView.Columns("EnrollmentDate").Visible = False
// Initialize schoolContext. schoolContext = new SchoolEntities(); // Define the query to retrieve instructors. ObjectQuery<Person> instructorQuery = schoolContext.Person .Include("OfficeAssignment") .Where("it.HireDate is not null") .OrderBy("it.LastName"); // Execute and bind the instructorList control to the query. instructorGridView.DataSource = instructorQuery. Execute(MergeOption.OverwriteChanges); instructorGridView.Columns["EnrollmentDate"].Visible = false;
Vuelva a la vista de diseño del formulario InstructorViewer y haga doble clic en el control updateInstructorButton.
El controlador de eventos updateInstructor_Click se agrega al archivo de código subyacente.
Agregue el código al controlador de eventos updateInstructor_Click que guarda cualquier cambio realizado en la información del instructor en el control instructorGridViewDataGridView.
Dim numChanges As Integer ' Save object changes to the database, display a ' message, and refresh the form. numChanges = schoolContext.SaveChanges() MessageBox.Show(numChanges.ToString() + _ " change(s) saved to the database.") Me.Refresh()
int numChanges; // Save object changes to the database, display a // message, and refresh the form. numChanges = schoolContext.SaveChanges(); MessageBox.Show(numChanges.ToString() + " change(s) saved to the database."); this.Refresh();
Presione Ctrl + F5 para ejecutar la aplicación. La información del instructor se puede ver y actualizar ahora haciendo clic en View Instructors, realizando modificaciones en la tabla que aparece y haciendo clic en Update Instructor.
Ver y actualizar la información de Office
En este procedimiento, agregará código al formulario OfficeViewer que le permita ver y actualizar la información de la asignación de oficina. Más específicamente, el código hace lo siguiente:
Enlaza el ComboBox a una consulta que devuelve información del instructor.
Muestra información de la ubicación de la oficina para el instructor seleccionado en TextBox.
Utiliza los procedimientos almacenados que asignamos anteriormente para escribir los datos en la base de datos al llamar a SaveChanges() en el controlador de eventos updateOffice_Click.
Para ver y actualizar información de la oficina
Con el formulario OfficeViewer abierto en el diseñador de formularios, haga doble clic en el formulario OfficeViewer.
El archivo de código subyacente para el formulario OfficeViewer se abre.
Agregue las instrucciones using (C#) o Imports (Visual Basic) siguientes:
Imports System.Data.Objects Imports System.Data.Objects.DataClasses
using System.Data.Objects; using System.Data.Objects.DataClasses;
Agregue una propiedad a la clase OfficeViewer que representa el contexto del objeto:
' Create an ObjectContext instance based on SchoolEntity. Private schoolContext As SchoolEntities
// Create an ObjectContext instance based on SchoolEntity. private SchoolEntities schoolContext;
Agregue el método siguiente al formulario:
Private Sub ExecuteInstructorQuery() ' Define the query to retrieve instructors. Dim instructorQuery As ObjectQuery(Of Person) = _ schoolContext.Person.Include("OfficeAssignment"). _ Where("it.HireDate is not null").OrderBy("it.LastName") 'Execute and bind the instructorList control to the query. 'Using MergeOption.OverwriteChanges overwrites local data 'with data from the database. instructorList.DataSource = instructorQuery _ .Execute(MergeOption.OverwriteChanges) instructorList.DisplayMember = "LastName" End Sub
private void ExecuteInstructorQuery() { // Define the query to retrieve instructors. ObjectQuery<Person> instructorQuery = schoolContext.Person .Include("OfficeAssignment") .Where("it.HireDate is not null") .OrderBy("it.LastName"); //Execute and bind the instructorList control to the query. //Using MergeOption.OverwriteChanges overwrites local data //with data from the database. instructorList.DataSource = instructorQuery .Execute(MergeOption.OverwriteChanges); instructorList.DisplayMember = "LastName"; }
Este método ejecuta una consulta que devuelve información del instructor y enlaza los resultados al control instructorListComboBox.
En el controlador de eventos OfficeViewer_Load, agregue el código para inicializar el contexto del objeto y llamar a un método que enlaza el control ComboBox a una consulta que devuelve todos los tipos Person que no tienen el valor null en HireDate.
schoolContext = New SchoolEntities() ExecuteInstructorQuery()
schoolContext = new SchoolEntities(); ExecuteInstructorQuery();
Vuelva a la vista de diseño del formulario OfficeViewer y haga doble clic en el control instructorListComboBox.
El controlador de eventos instructorList_SelectedIndexChanged se agrega al archivo de código subyacente.
Agregue el código al controlador de eventos que muestra la ubicación de la oficina del instructor seleccionado en el control ListBox y deshabilita el control updateOfficeButton. Este control se habilitará cuando se realice un cambio en la ubicación de una oficina seleccionada.
Dim instructor As Person = CType(Me.instructorList _ .SelectedItem(), Person) If Not instructor.OfficeAssignment Is Nothing Then Me.officeLocation.Text = instructor _ .OfficeAssignment.Location.ToString() Else Me.officeLocation.Text = "" End If ' Disable the updateOffice button until a change ' has been made to the office location. updateOffice.Enabled = False 'forceChanges.Enabled = False
Person instructor = (Person)this.instructorList. SelectedItem; if (instructor.OfficeAssignment != null) { this.officeLocation.Text = instructor. OfficeAssignment.Location.ToString(); } else { this.officeLocation.Text = ""; } // Disable the updateOffice button until a change // has been made to the office location. updateOffice.Enabled = false; //forceChanges.Enabled = false;
Vuelva a la vista de diseño del formulario OfficeViewer y haga doble clic en el control updateOfficeButton.
El controlador de eventos updateOffice_Click se agrega al archivo de código subyacente.
Agregue el código que guarda los cambios realizados en la información de oficina en el control officeLocationTextBox:
Try Dim numChanges As Integer Dim currentInstructor As Person = CType(Me.instructorList _ .SelectedItem(), Person) If Me.officeLocation.Text <> String.Empty Then If Not currentInstructor.OfficeAssignment Is Nothing Then currentInstructor.OfficeAssignment.Location() = _ Me.officeLocation.Text Else Dim temp(8) As Byte currentInstructor.OfficeAssignment = _ OfficeAssignment.CreateOfficeAssignment( _ currentInstructor.PersonID, _ Me.officeLocation.Text, temp) End If Else schoolContext.DeleteObject(currentInstructor. _ OfficeAssignment) End If numChanges = schoolContext.SaveChanges() MessageBox.Show(numChanges.ToString() _ + " change(s) saved to the database.") Catch oce As OptimisticConcurrencyException MessageBox.Show(oce.Message + " The conflict " & _ "occurred on " & oce.StateEntries(0).Entity _ .ToString() & "with key value " & _ oce.StateEntries(0).EntityKey.EntityKeyValues(0) _ .Value) 'forceChanges.Enabled = True Catch ue As UpdateException MessageBox.Show(ue.Message & " Click OK to retrieve " _ & "the latest data from the database.") ExecuteInstructorQuery() Me.Refresh() Finally ' Disable the updateOffice button until another ' change has been made to the location. updateOffice.Enabled = False End Try
try { int numChanges; Person currentInstructor = (Person)this.instructorList. SelectedItem; if (this.officeLocation.Text != string.Empty) { if (currentInstructor.OfficeAssignment != null) { currentInstructor.OfficeAssignment.Location = this.officeLocation.Text; } else { currentInstructor.OfficeAssignment = OfficeAssignment.CreateOfficeAssignment( currentInstructor.PersonID, this.officeLocation.Text, new byte[8]); } } else { schoolContext.DeleteObject(currentInstructor .OfficeAssignment); } numChanges = schoolContext.SaveChanges(); MessageBox.Show(numChanges.ToString() + " change(s) saved to the database."); } catch (OptimisticConcurrencyException oce) { MessageBox.Show(oce.Message + " The conflict " + "occurred on " + oce.StateEntries[0].Entity + " with key value " + oce.StateEntries[0]. EntityKey.EntityKeyValues[0].Value); //forceChanges.Enabled = true; } catch (UpdateException ue) { MessageBox.Show(ue.Message + " Click OK to retrieve " + "the latest data from the database."); ExecuteInstructorQuery(); this.Refresh(); } finally { // Disable the updateOffice button until another // change has been made to the location. updateOffice.Enabled = false; }
Vuelva a la vista de diseño del formulario OfficeViewer y haga doble clic en el control officeLocationTextBox.
El controlador de eventos officeLocation_TextChanged se agrega al archivo de código subyacente.
Agregue código para habilitar el control updateOfficeButton cuando se haya realizado un cambio en la ubicación de la oficina seleccionada:
' Enable the udateOffice button when there is a change ' to write to the database. updateOffice.Enabled = True
// Enable the udateOffice button when there is a change // to write to the database. updateOffice.Enabled = true;
La aplicación se ha completado ahora. Presione Ctrl+F5 para ejecutar la aplicación. Ahora puede ver y actualizar la información de oficina en el formulario OfficeViewer.
Administrar los conflictos de simultaneidad
En este procedimiento, agregará código al formulario Office Viewer que aplique los cambios del cliente a la base de datos después de producirse un conflicto de simultaneidad.
Para administrar los conflictos de simultaneidad
Haga doble clic en InstructorViewer.vb o en InstructorViewer.cs en el Explorador de soluciones.
El formulario se abre el diseñador de formularios.
Haga doble clic en el botón View Offices.
El archivo de código subyacente para el formulario InstructorViewer se abre.
Agregue el código siguiente al controlador de eventos viewOffices_Click para que se carguen dos formularios OfficeViewer cuando se hace clic en el botón View Offices.
Dim officeViewer2 As New OfficeViewer() officeViewer2.Text = "Demonstrate Conflict" officeViewer2.Visible = True
OfficeViewer officeViewer2 = new OfficeViewer(); officeViewer2.Text = "Demonstrate Conflict"; officeViewer2.Visible = true;
Haga doble clic en OfficeViewer.vb o en OfficeViewer.cs en el Explorador de soluciones.
El formulario se abre el diseñador de formularios.
Arrastre un control Button del cuadro de herramientas al formulario. Establezca el valor de Nombre en forceChanges y el de Texto en Force Changes.
Haga doble clic en el botón Force Changes.
El archivo de código subyacente para el formulario Office Viewer se abre.
Agregue el código siguiente al controlador de eventos forceChanges_Click para que se apliquen al servidor los cambios en el cliente o los datos enlazados al control instructorListComboBox se actualicen desde la base de datos.
Dim numChanges As Integer Dim currentInstructor As Person = CType(Me.instructorList _ .SelectedItem(), Person) Try currentInstructor.OfficeAssignment.Location = _ Me.officeLocation.Text ' Using RefreshMode.ClientWins disables the ' optimistic concurrency check. schoolContext.Refresh(RefreshMode.ClientWins, _ currentInstructor.OfficeAssignment) numChanges = schoolContext.SaveChanges() MessageBox.Show(numChanges.ToString() + _ " change(s) saved to the database.") 'forceChanges.Enabled = False Catch ioe As InvalidOperationException MessageBox.Show(ioe.Message + " Click OK to retrieve " _ + "the latest data from the database.") ExecuteInstructorQuery() Me.Refresh() End Try
int numChanges; Person currentInstructor = (Person)this.instructorList .SelectedItem; try { currentInstructor.OfficeAssignment.Location = this.officeLocation.Text; // Using RefreshMode.ClientWins disables the // optimistic concurrency check. schoolContext.Refresh(RefreshMode.ClientWins, currentInstructor.OfficeAssignment); numChanges = schoolContext.SaveChanges(); MessageBox.Show(numChanges.ToString() + " change(s) saved to the database."); //forceChanges.Enabled = false; } catch (InvalidOperationException ioe) { MessageBox.Show(ioe.Message + " Click OK to retrieve " + "the latest data from the database."); ExecuteInstructorQuery(); this.Refresh(); }
Quite los comentarios de la línea de código
forceChanges = False
(Visual Basic) oforceChanges = false;
(C#) en el controlador de eventos instructorList_SelectedIndexChanged para que el botón Force Changes se deshabilite cuando se seleccione un instructor nuevo.Quite los comentarios de la línea de código
forceChanges = True
(Visual Basic) oforceChanges = true;
(C#) en el controlador de eventos updateOffice_Click para que el botón Force Changes se habilite cuando se produzca un conflicto de simultaneidad.Quite los comentarios de la línea de código
forceChanges = False
(Visual Basic) oforceChanges = false;
(C#) en el controlador de eventos forceChanges_Click para que el botón Force Changes se deshabilite una vez aplicados los cambios a la base de datos.
Para ver cómo administra la aplicación un conflicto de simultaneidad, ejecute la aplicación (presione Ctrl+F5), haga clic en View Instructors y, a continuación, haga clic en View Offices. Actualice la ubicación de una oficina en el formulario Office Viewer e intente actualizar la misma ubicación de oficina en el otro formulario Demonstrate Conflict. Aparecerá un cuadro de mensaje para notificar el conflicto de simultaneidad. Para aplicar los cambios del formulario Demonstrate Conflict a la base de datos, haga clic en Force Changes.
Códigos
Esta sección contiene las versiones finales de los archivos de código subyacente para los formularios OfficeViewer e InstructorViewer.
Imports System.Data.Objects
Imports System.Data.Objects.DataClasses
Public Class InstructorViewer
' Create an ObjectContext instance based on SchoolEntity.
Private schoolContext As SchoolEntities
Private Sub viewOffices_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles viewOffices.Click
Dim officeViewer As New OfficeViewer()
officeViewer.Visible = True
Dim officeViewer2 As New OfficeViewer()
officeViewer2.Text = "Demonstrate Conflict"
officeViewer2.Visible = True
End Sub
Private Sub InstructorViewer_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
' Initialize the ObjectContext.
schoolContext = New SchoolEntities()
Dim instructorQuery As ObjectQuery(Of Person) = _
schoolContext.Person.Include("OfficeAssignment") _
.Where("it.HireDate is not null") _
.OrderBy("it.LastName")
instructorGridView.DataSource = instructorQuery _
.Execute(MergeOption.OverwriteChanges)
instructorGridView.Columns("EnrollmentDate").Visible = False
End Sub
Private Sub updateInstructor_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles updateInstructor.Click
Dim numChanges As Integer
' Save object changes to the database, display a
' message, and refresh the form.
numChanges = schoolContext.SaveChanges()
MessageBox.Show(numChanges.ToString() + _
" change(s) saved to the database.")
Me.Refresh()
End Sub
End Class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
namespace CourseManager
{
public partial class InstructorViewer : Form
{
// Create an ObjectContext instance based on SchoolEntity.
private SchoolEntities schoolContext;
public InstructorViewer()
{
InitializeComponent();
}
private void viewOffices_Click(object sender, EventArgs e)
{
OfficeViewer officeViewer = new OfficeViewer();
officeViewer.Visible = true;
OfficeViewer officeViewer2 = new OfficeViewer();
officeViewer2.Text = "Demonstrate Conflict";
officeViewer2.Visible = true;
}
private void InstructorViewer_Load(object sender, EventArgs e)
{
// Initialize schoolContext.
schoolContext = new SchoolEntities();
// Define the query to retrieve instructors.
ObjectQuery<Person> instructorQuery = schoolContext.Person
.Include("OfficeAssignment")
.Where("it.HireDate is not null")
.OrderBy("it.LastName");
// Execute and bind the instructorList control to the query.
instructorGridView.DataSource = instructorQuery.
Execute(MergeOption.OverwriteChanges);
instructorGridView.Columns["EnrollmentDate"].Visible = false;
}
private void updateInstructor_Click(object sender, EventArgs e)
{
int numChanges;
// Save object changes to the database, display a
// message, and refresh the form.
numChanges = schoolContext.SaveChanges();
MessageBox.Show(numChanges.ToString() +
" change(s) saved to the database.");
this.Refresh();
}
}
}
Imports System.Data.Objects
Imports System.Data.Objects.DataClasses
Public Class OfficeViewer
' Create an ObjectContext instance based on SchoolEntity.
Private schoolContext As SchoolEntities
Private Sub OfficeViewer_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
schoolContext = New SchoolEntities()
ExecuteInstructorQuery()
End Sub
Private Sub instructorList_SelectedIndexChanged(ByVal sender As _
System.Object, ByVal e As System.EventArgs) Handles _
instructorList.SelectedIndexChanged
Dim instructor As Person = CType(Me.instructorList _
.SelectedItem(), Person)
If Not instructor.OfficeAssignment Is Nothing Then
Me.officeLocation.Text = instructor _
.OfficeAssignment.Location.ToString()
Else
Me.officeLocation.Text = ""
End If
' Disable the updateOffice button until a change
' has been made to the office location.
updateOffice.Enabled = False
'forceChanges.Enabled = False
End Sub
Private Sub updateOffice_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles updateOffice.Click
Try
Dim numChanges As Integer
Dim currentInstructor As Person = CType(Me.instructorList _
.SelectedItem(), Person)
If Me.officeLocation.Text <> String.Empty Then
If Not currentInstructor.OfficeAssignment Is Nothing Then
currentInstructor.OfficeAssignment.Location() = _
Me.officeLocation.Text
Else
Dim temp(8) As Byte
currentInstructor.OfficeAssignment = _
OfficeAssignment.CreateOfficeAssignment( _
currentInstructor.PersonID, _
Me.officeLocation.Text, temp)
End If
Else
schoolContext.DeleteObject(currentInstructor. _
OfficeAssignment)
End If
numChanges = schoolContext.SaveChanges()
MessageBox.Show(numChanges.ToString() _
+ " change(s) saved to the database.")
Catch oce As OptimisticConcurrencyException
MessageBox.Show(oce.Message + " The conflict " & _
"occurred on " & oce.StateEntries(0).Entity _
.ToString() & "with key value " & _
oce.StateEntries(0).EntityKey.EntityKeyValues(0) _
.Value)
'forceChanges.Enabled = True
Catch ue As UpdateException
MessageBox.Show(ue.Message & " Click OK to retrieve " _
& "the latest data from the database.")
ExecuteInstructorQuery()
Me.Refresh()
Finally
' Disable the updateOffice button until another
' change has been made to the location.
updateOffice.Enabled = False
End Try
End Sub
Private Sub officeLocation_TextChanged(ByVal sender As _
System.Object, ByVal e As System.EventArgs) _
Handles officeLocation.TextChanged
' Enable the udateOffice button when there is a change
' to write to the database.
updateOffice.Enabled = True
End Sub
Private Sub forceChanges_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles forceChanges.Click
Dim numChanges As Integer
Dim currentInstructor As Person = CType(Me.instructorList _
.SelectedItem(), Person)
Try
currentInstructor.OfficeAssignment.Location = _
Me.officeLocation.Text
' Using RefreshMode.ClientWins disables the
' optimistic concurrency check.
schoolContext.Refresh(RefreshMode.ClientWins, _
currentInstructor.OfficeAssignment)
numChanges = schoolContext.SaveChanges()
MessageBox.Show(numChanges.ToString() + _
" change(s) saved to the database.")
'forceChanges.Enabled = False
Catch ioe As InvalidOperationException
MessageBox.Show(ioe.Message + " Click OK to retrieve " _
+ "the latest data from the database.")
ExecuteInstructorQuery()
Me.Refresh()
End Try
End Sub
Private Sub ExecuteInstructorQuery()
' Define the query to retrieve instructors.
Dim instructorQuery As ObjectQuery(Of Person) = _
schoolContext.Person.Include("OfficeAssignment"). _
Where("it.HireDate is not null").OrderBy("it.LastName")
'Execute and bind the instructorList control to the query.
'Using MergeOption.OverwriteChanges overwrites local data
'with data from the database.
instructorList.DataSource = instructorQuery _
.Execute(MergeOption.OverwriteChanges)
instructorList.DisplayMember = "LastName"
End Sub
End Class
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
namespace CourseManager
{
public partial class OfficeViewer : Form
{
// Create an ObjectContext instance based on SchoolEntity.
private SchoolEntities schoolContext;
public OfficeViewer()
{
InitializeComponent();
}
private void OfficeViewer_Load(object sender, EventArgs e)
{
schoolContext = new SchoolEntities();
ExecuteInstructorQuery();
}
private void instructorList_SelectedIndexChanged(object sender,
EventArgs e)
{
Person instructor = (Person)this.instructorList.
SelectedItem;
if (instructor.OfficeAssignment != null)
{
this.officeLocation.Text = instructor.
OfficeAssignment.Location.ToString();
}
else
{
this.officeLocation.Text = "";
}
// Disable the updateOffice button until a change
// has been made to the office location.
updateOffice.Enabled = false;
//forceChanges.Enabled = false;
}
private void updateOffice_Click(object sender, EventArgs e)
{
try
{
int numChanges;
Person currentInstructor = (Person)this.instructorList.
SelectedItem;
if (this.officeLocation.Text != string.Empty)
{
if (currentInstructor.OfficeAssignment != null)
{
currentInstructor.OfficeAssignment.Location
= this.officeLocation.Text;
}
else
{
currentInstructor.OfficeAssignment
= OfficeAssignment.CreateOfficeAssignment(
currentInstructor.PersonID, this.officeLocation.Text,
new byte[8]);
}
}
else
{
schoolContext.DeleteObject(currentInstructor
.OfficeAssignment);
}
numChanges = schoolContext.SaveChanges();
MessageBox.Show(numChanges.ToString() +
" change(s) saved to the database.");
}
catch (OptimisticConcurrencyException oce)
{
MessageBox.Show(oce.Message + " The conflict "
+ "occurred on " + oce.StateEntries[0].Entity
+ " with key value " + oce.StateEntries[0].
EntityKey.EntityKeyValues[0].Value);
//forceChanges.Enabled = true;
}
catch (UpdateException ue)
{
MessageBox.Show(ue.Message + " Click OK to retrieve "
+ "the latest data from the database.");
ExecuteInstructorQuery();
this.Refresh();
}
finally
{
// Disable the updateOffice button until another
// change has been made to the location.
updateOffice.Enabled = false;
}
}
private void officeLocation_TextChanged(object sender, EventArgs e)
{
// Enable the udateOffice button when there is a change
// to write to the database.
updateOffice.Enabled = true;
}
private void forceChanges_Click(object sender, EventArgs e)
{
int numChanges;
Person currentInstructor = (Person)this.instructorList
.SelectedItem;
try
{
currentInstructor.OfficeAssignment.Location
= this.officeLocation.Text;
// Using RefreshMode.ClientWins disables the
// optimistic concurrency check.
schoolContext.Refresh(RefreshMode.ClientWins,
currentInstructor.OfficeAssignment);
numChanges = schoolContext.SaveChanges();
MessageBox.Show(numChanges.ToString() +
" change(s) saved to the database.");
//forceChanges.Enabled = false;
}
catch (InvalidOperationException ioe)
{
MessageBox.Show(ioe.Message + " Click OK to retrieve "
+ "the latest data from the database.");
ExecuteInstructorQuery();
this.Refresh();
}
}
private void ExecuteInstructorQuery()
{
// Define the query to retrieve instructors.
ObjectQuery<Person> instructorQuery = schoolContext.Person
.Include("OfficeAssignment")
.Where("it.HireDate is not null")
.OrderBy("it.LastName");
//Execute and bind the instructorList control to the query.
//Using MergeOption.OverwriteChanges overwrites local data
//with data from the database.
instructorList.DataSource = instructorQuery
.Execute(MergeOption.OverwriteChanges);
instructorList.DisplayMember = "LastName";
}
}
}
Pasos siguientes
Ha asignado correctamente las operaciones de inserción, actualización y eliminación de una entidad a procedimientos almacenados. Para obtener más información sobre la compatibilidad con los procedimientos almacenados en Entity Framework, vea Compatibilidad con los procedimientos almacenados (Entity Framework). Para obtener más información sobre cómo generar aplicaciones que utilizan Entity Framework, vea Guía de programación (Entity Framework).
Vea también
Otros recursos
Escenarios de ADO.NET Entity Data Model Designer
Tareas de herramientas de Entity Data Model