Download - Entity Framework

Transcript

CASTRO PECHO REYNALDOARQUITECTURA DE SOFTWAREEntity FrameworkQue es ?ElADO.NETEntity Frameworkes un conjunto deAPIsde acceso a datos para el Microsoft .NET Framework, apuntando a la versin de ADO.NET que se incluye con el.NET Framework 3.5. Fue lanzado como actualizacin separada junto con el Service Pack 1 para el .NET Framework, despus del lanzamiento de tanto el .NET Framework 3.5 y el Visual Studio 2008. Una nueva versin del Entity Framework (v 4.0) ser liberada junto al Visual Studio 2010 y el .NET Framework 4.0.Una entidad delEntity Frameworkes un objeto que tiene una clave representando la clave primaria de una entidad lgica de datastore. Un modelo conceptual Entity Data Model (modelo Entidad-Relacin) es mapeado a un modelo de esquema de datastore. Usando el Entity Data Model, el Framework permite que los datos sean tratados como entidades independientemente de sus representaciones del datastore subyacente.El Entity SQL es un lenguaje similar al SQL para consultar el Entity Data Model (en vez del datastore subyacente). Similarmente, las extensiones del Linq, Linq-to-Entities, proporcionan consultas tipeadas en el Entity Data Model. Las consultas Entity SQL y Linq-to-Entities son convertidas internamente en un Canonical Query Tree que entonces es convertido en una consulta comprensible al datastore subyacente (ej. en SQL en el caso de una base de datos relacional). Las entidades pueden utilizar sus relaciones, y sus cambios enviados de regreso al datastore.

Para qu sirve?Entity Framework (EF) sirve para mapeador objeto-relacional que permite a los desarrolladores de. NET para trabajar con datos relacionales usando objetos de dominio especfico. Se elimina la necesidad de que la mayor parte del cdigo de acceso a datos que los desarrolladores en general tienen que escribir.

Como Implementa El Patrn Repository Entity Framework?Patrones de diseo: RepositoryPara poder implementar el patrn repository y entity framework tenemos que tener los siguientes pasos.Data MapperImaginemos que tenemos un sistema de almacenamiento de datos complejo, algo as como una base de datos. La gestin mediante nuestro lenguaje de programacin preferido de esta informacin, puede resultar compleja y para nada relacionada con la forma de gestionar la informacin dentro de nuestra aplicacin.Por citar un ejemplo ms concreto, no resulta sencillo ni natural, recoger un dato de la una base de datos SQL Server, usando c#. Bsicamente porque el lenguaje c# est pensado para programar orientado a objetos y el motor de SQL Server est pensado para modelos de datos relacionales usando SQL como lenguaje de comunicacin.Una consulta sencilla, que devuelva el nmero de usuarios de nuestro sistema, puede ocupar varias lneas. Y adems, habr que tener en cuenta los errores que puedan surgir:

123456789101112131415try{using(var con = new SqlConnection(connetionString)){using (var cmd = new SqlCommand("select count(*) from [dbo].[Users]", con)){var count = Convert.ToInt32(cmd.ExecuteScalar());return count;}}} catch (Exception ex){// manage exception}

Para que no se complique nuestro cdigo, el seor Fowler nos propone crear una capa dentro de nuestra aplicacin cuya misin sea mover la informacin entre los objetos de c# y la base de datos. Adems esta capa va a aislar el comportamiento de la base de datos, del de nuestros objetos, haciendo que nuestra aplicacin no est acoplada con nuestra fuente de almacenamiento (SQL Server en el ejemplo).

De esta forma crearamos una implementacin simple y genrica de nuestra capa de Data Mapper:

1234567891011121314151617181920212223242526272829303132333435363738public interface IDataMapper where TObject : class{void Insert(TObject obj);void Update(TObject obj);void Delete(TObject obj);IEnumerable GetAll();}public class UserDataMapper : IDataMapper{private string connetionString;public UserDataMapper(string connetionString){this.connetionString = connetionString;}public void Insert(User user){try{using(var con = new SqlConnection(connetionString)){var sql = "INSERT INTO USER (UserId, [Name], LastName, Email) VALUES (@userId, @name, @lastName, @email)";using (var cmd = new SqlCommand(sql, con)){cmd.Parameters.Add(new SqlParameter("userId", user.UserId));cmd.Parameters.Add(new SqlParameter("name", user.Name));cmd.Parameters.Add(new SqlParameter("lastName", user.LastName));cmd.Parameters.Add(new SqlParameter("email", user.Emaild));cmd.ExecuteNonQuery();}}}catch(Exception ex){throw new DataMapperException("Error inserting a User", ex);}}public void Update(TObject obj) { /*...*/ }public void Delete(TObject obj) { /*...*/ }public IEnumerable GetAll() { /*...*/ }}

Un objeto Data Mapper es un tipo de implementacin de DAO (Data Access Object). La peculiaridad es que hace uso de un patrn Metadata Mapper. La idea es aadir una especie de diccionario (o Hashtable) que contenga las equivalencias entre los objetos de c# y las tablas de SQL Server. Pero esto quiz sea otra historia

RepositoryUna vez hemos montado nuestra capa de Data Mapper, al ir construyendo el resto de la aplicacin, nos vamos dando cuenta de que necesitamos crear un mtodo que acepte condiciones y filtros para realizar un gran nmero de consultas diferentes. Por ejemplo, necesitamos listados de usuarios paginados, listados de usuarios para mostrar en un control de tipo ComboBox, e incluso los usuarios que su nombre sea Pepe. Entonces, como resultado de este requerimiento tan genrico, tendramos una funcin parecida a esta:

123456public interface IDataMapper where TObject : class{/* ... */IEnumerable GetFiltered(string conditions, string order, int pageSize, int pageIndex);}

As tendramos la libertad de llamar a nuestro objeto UserDataMapper de formas diferentes:123456var userDataMapper = new UserDataMapper(conStr);// seleccionar los usuarios de nombre 'Pepe', ordenados por el apellido, paginando de 10 en 10, y quiero la primera pginauserDataMapper.GetFiltered("Name = 'Pepe'", "LastName", 10, 1);// seleccionar los usuarios de apellido 'Perez',sin orden, con el tamao de pgina ms grande que pueda, dame la pginauserDataMapper.GetFiltered("LastName = 'Perez' AND Email LIKE '%@mail.com'", "", int.MaxValue, 1);

Pero el lenguaje de nuestro almacn de informacin (SQL), no debera ser manejado desde la capa que gestiona el negocio de la aplicacin.Es entonces cuando quiz nos vendra bien implementar otra capa nueva de abstraccin por encima de Data Mapper. Una capa que nos ayude gestionar estas consultas de forma transparente, sin necesidad de acabar escribiendo cdigo SQL y manteniendo desacoplado el cdigo de negocio, de la forma de almacenar la informacin.El Repository surge como un sofisticado patrn que da solucin a este problema. Decimos sofisticado porque se podra definir como una combinacin de otros patrones.La idea es que un objeto Repository acte como una coleccin en memoria del modelo de dominio. A esta coleccin de objetos podremos aadirle o quitarle elementos y adems realizar bsquedas filtradas utilizando el patrn Specification:12345public interface IRepository : ICollectionwhere TEntity : class{IEnumerable FilterBy(ICriteria criteria);}

La primera caracterstica que puede llamarnos la atencin al definir Repository es el concepto demodelo de dominio. Esto es un trmino muy comn cuando hablamos deDDD(Domain Driven Design), y quiere decir que nuestra aplicacin tiene un modelo principal al que llamaremos dominio. Este modelo se diferencia del modelo de la base de datos en su concepcin. En lugar de pensar cmo vamos a almacenar las tablas y sus relaciones dentro de una base de datos, lo que vamos a hacer es pensar en la mejor forma de gestionar los objetos dentro del contexto de nuestro lenguaje de programacin y de la forma que mejor se adapte a las tareas de negocio.Y si estudiamos la implementacin propuesta, encontraremos varios detalles. Entre ellos que nuestro repositorio tendr que implementar ICollection, por lo que implementar funciones como Add que aade un objeto nuevo, o Remove que borra el objeto de la coleccin.Otro detalle es el objeto ICriteria que se le pasa como parmetro al mtodo FilterBy. Este objeto no es ms que la representacin del anteriormente mencionado patrn Specification.SpecificationEl patrn Specification viene a resolver un problema de crear diferentes reglas de negocio que puedan ser combinadas. Esto quiere decir que nos ayudar a crear diferentes normas que resolvern un problema concreto de formas diferentes. Pero para orientarnos ms rpido, vamos a ver un ejemplo de implementacin:

1234567891011public interface ISpecification {bool IsSatisfiedBy(object candidate);}public interface ICompositeSpecification : ISpecification {ISpecification And(ISpecification other);ISpecification Or(ISpecification other);ISpecification Not();}

Implementando de la forma correcta este patrn, el resultado que tendramos es que si tuviramos diferentes especificaciones, podramos combinarlas para conseguir algo ms concreto.Imaginemos que tenemos estas implementaciones:

1234567891011121314151617public class NameSpecification : ICompositeSpecification {public NameSpecification(string nameToCompare) { /* ... */ } public bool IsSatisfiedBy(object candidate) { /* candidate.Name == this.nameToCompare ... */ }public ISpecification And(ISpecification other) { /* ... */ } public ISpecification Or(ISpecification other) { /* ... */ } public ISpecification Not() { /* ... */ } }public class PageIndexSpecification : ICompositeSpecification {public NameSpecification(int pageIndex, int pageSize) { /* ... */ } public bool IsSatisfiedBy(object candidate) { /* candidate is un pageIndex using pageSize */ }public ISpecification And(ISpecification other) { /* ... */ } public ISpecification Or(ISpecification other) { /* ... */ } public ISpecification Not() { /* ... */ } }

Ahora podramos llamar a nuestro repositorio con un cdigo parecido a este:

12345var repository = new UserRepository();var criteria = new NameSpecification("Pepe"); // filtramos por nombre igual que "Pepe"criteria = criteria.And(new PageIndexCriteria(1, 10)); // cogemos la primera pginavar result = repositori.FilterBy(criteria);

La ventaja de este patrn es que podemos crear especificaciones muy genricas o muy concretas, segn las necesidades de cada momento:

12345678public class PropertyEqualsSpecification : ICompositeSpecification {public NameSpecification(string propertyName, object value) { /* ... */ } public bool IsSatisfiedBy(object candidate) { /* candidate.propertyName == value ... */ }public ISpecification And(ISpecification other) { /* ... */ } public ISpecification Or(ISpecification other) { /* ... */ } public ISpecification Not() { /* ... */ } }

Dentro de este patrn, existe una implementacin muy conocida para ayudarnos a realizar sentencias SQL para bases de datos, y recibe el nombre deQuery Object, tambin expuesto en el libro dePatterns of Enterprise Application Architecture.Lo que se propone en el patrn Repository es que las especificaciones sean resueltas usando unpatrn Strategypara poder determinar en ltima instancia una sentencia correcta que podamos enviar a nuestro objeto Data Mapper.Y como corolario a esta definicin, aquellas especificaciones que sean muy comunes y se repitan muchas veces a lo largo del cdigo, pueden pasar a formar parte de la definicin del propio repositorio. Imaginemos que la bsqueda por nombre se realiza en 10 sitios diferentes. La solucin ms ptima ser crear un mtodo especfico dentro del repositorio:

123456789public class UserRepository : IRepository {/* ... */public IEnumerable FilterByName(string name) {var criteria = new NameSpecification(name);return this.FilterBy(criteria); } }

La actualidadHasta este momento hemos hablado de la teora del patrn Repository y como lo encontramos definido la primera vez que lemos algo sobre l. Pero probablemente, si realizamos una bsqueda por internet sobre este patrn, y ms si buscamos su implementacin concreta para el lenguaje de programacin c#, nos encontraremos un resultado que apenas se parece con al que acabamos de definir.Vamos a poner el ejemplo de un blog simple, en el que queremos almacenar las entradas que escribimos Post y los comentarios que dejan los visitantes dentro de esas entradas Comment:

Si seguimos a rajatabla la primera implementacin que encontremos en los buscadores ms conocidos, el resultado ser algo parecido a esto:

12345678910111213public interface IRepository where TEntity : class{IQueryable GetAll();void Add(TEntity entity);void Update(TEntity entity);void Delete(TEntity entity);}public interface IPostRepository : IRepository{}public interface ICommentRepository : IRepository{}

Qu ha pasado?En los entornos de programacin en .net, ha cambiado mucho el escenario respecto de los inicios de la plataforma con respecto las libreras y evoluciones del lenguaje de hoy en da. Y estas nuevas caractersticas han provocado que el patrn Repository tenga que ser adaptado a unas nuevas necesidades.En la versin 3.5 de la framework, como gran novedad se aadi de forma nativa LINQ (Language INtegrated Query). Una nueva extensin al lenguaje que nos iba a permitir realizar sentencias muy semejantes a las de SQL, dentro de entornos de programacin .net:

123var results = from c in SomeCollectionwhere c.SomeProperty < 10select new {c.SomeProperty, c.OtherProperty};

Si tenemos una coleccin, un array o cualquier objeto que implemente el patrn Iterator (objetos que implementan IEnumerable), podemos recorrerla de forma sencilla y hacer una gestin de sus datos de una forma similar a como trabajamos en los entornos de bases de datos.Este tipo de consultas funcionan gracias a unas extensiones del lenguaje que transforman las sentencias en llamadas a una serie de funciones nuevas. Por ejemplo, al compilar el ejemplo anterior, lo que en realidad tenemos como resultado es:123var results = SomeCollection.Where(c => c.SomeProperty < 10).Select( c => new { c.SomeProperty, c.OtherProperty });

Algunos rpidamente habrn encontrado que este cdigo podra ser una implementacin vlida del patrn Specification que antes estamos mencionando. Adems LINQ trabaja con colecciones, por lo que podramos decir que esta tecnologa realiza por nosotros la mitad del trabajo de crear un repositorio.La otra gran novedad son los ORM (Object Relational Mapping) modernos, que antiguamente nos ayudaban a crear objetos DAO, pero que hoy en da han llegado mucho ms lejos. Libreras como Entity Framework o nHibernate han conseguido implementar complejos sistemas que gestionan las conexiones con las bases de datos, mapeo automtico de todo lo que podamos encontrar a objetos planos y simples, cachs, generacin de bases de datos automtica, e incluso su propio lenguaje intermedio para realizar sentencias estndares de bases de datos.Adems uniendo estos ORM con LINQ, se ha cerrado el crculo. Por ejemplo, un contexto de EF tiene colecciones de entidades de la base de datos. A estas colecciones uno puede aadirle o quitarle elementos, y tambin se pueden realizar consultas complejas expresadas en un lenguaje cercano al natural y al de una base de datos:1234public class MyDbContext : DbContext{public DbSet MyEntities { get; set; }}

1234567891011var context = new MyDbContext();var myEntity = new MyEntity { Name = "Test" };// aade la entidad a la base de datoscontext.MyEntities.Add(myEntity); // borra la entidad de la base de datoscontext.MyEntities.Delete(myEntity); // seleccionamos valores de la base de datos con condicionesvar results = context.MyEntities.Where( e => e.Name.StartsWith("T") );

Las conclusiones que podemos sacar de esto es que los ORMs modernos ya han implementado el patrn Repository por nosotros y lo han dotado de ms caractersticas.El nuevo RepositoryPero ahora imaginemos que queremos realizar pruebas unitarias en nuestra aplicacin o que por ejemplo quisiramos migrar a un nuevo motor de base de datos NoSQL. El ejemplo de contexto anterior no estara demasiado acoplado al ORM?Para solucionar esto existen varias formas, pero una de ellas es la de crear un objeto intermediario al que llamaremos Repository. Se usar ese nombre ya que va compartir ciertas caractersticas del patrn original y adems porque servir de repositorio de informacin para nuestra aplicacin.Un repositorio dentro de una aplicacin actual va a aislar al dominio del ORM (o de la conexin con la base de datos). Va a proveer de interfaces que puedan ser probadas y simuladas, adems de ocultar cualquier detalle relacionado con la forma de almacenar la informacin en nuestra aplicacin.Volviendo al ejemplo:

1234567public interface IRepository{IQueryable GetAll();void Add(TEntity entity);void Update(TEntity entity);void Delete(TEntity entity);}

Todo repositorio de la aplicacin expondr, al menos, los mtodos para aadir, borrar y listar elementos.En dependencia del ORM, un repositorio se implementar de una forma u otra, pudiendo gestionar transacciones, ciclo de vida de las conexiones, mapeo de objetos, etc.Otra propuestaPersonalmente esta ltima definicin no me convence del todo por varias razones:La primera es que no aporta valor real. Por lo general, crear repositorios se ha convertido en copiar y pegar cdigo, generarlo automticamente con plantillas t4 o cualquier herramienta semejante, y no nos paramos a pensar que es lo que esperamos de este tipo de artefacto.La segunda razn est relacionado con devolver objetos que implementan IQueryable. Estos objetos pueden ser gestionados usando LINQ, de tal forma que generen diferentes sentencias SQL en la base de datos, que por lo general son muy complejas y no todo lo eficientes que deberan.Adems, al usar objetos IQueryable en niveles lejanos al ORM o el repositorio, estamos dando responsabilidades extra a artefactos de nuestra aplicacin, que no estn preparados para estas responsabilidades. O dicho de otra forma, la ltima capa responsable de componer sentencias SQL (directa o indirectamente), debera ser el repositorio.Quiz sea muy atrevido entender LINQ como la implementacin ms correcta del patrn Specification dentro del contexto de un repositorio. Es posible que fuera ms correcto implementarla de nuevo, para poder aislar realmente el problema de las sentencias de consulta de base de datos eficientes a un solo lugar.La ltima razn por la que no termina de convencerme esta implementacin es el asunto de la existencia de un repositorio por cada una de las entidades de la base de datos. Algo que no tiene por qu adaptarse realmente a las necesidades de negocio. En el ejemplo del blog, si en lugar de tener un repositorio para objetos tipo Post y otro para Comment, podra ser ms lgico tener uno solo para gestionar las operaciones del blog. Porque si un comentario no tiene sentido si no est asociado con una entrada de un post, tampoco tendr sentido que tenga su propio repositorio.Aplicando estas premisas, personalmente y simplificando mucho el problema de la gestin de un blog, propondra un repositorio que aportara valor y no expusiera objetos IQueryable e implementara su propio sistema de especificaciones. Algo ms parecido a esto:?123456789101112131415161718192021222324252627282930313233343536373839404142434445

public abstract class BaseRepository{protected virtual IQueryable GetAll() where TEntity : class{/* ... */}protected virtual void Add(TEntity entity)where TEntity : class{/* ... */}protected virtual void Update(TEntity entity)where TEntity : class{/* ... */}protected virtual void Delete(TEntity entity)where TEntity : class{/* ... */}}public interface IBlogRepository : IBlogRepository{List GetAllPosts();List GetPostsByCriteria(ICriteria criteria);Post GetPostWithComments(Guid postId);void AddPost(Post post);void UpdatePost(Post post);void DeletePost(Post post);void InsertComment(Post post, Comment comment);void DeleteComment(Comment comment);/* ... */}public class BlogRepository : BaseRepository, IBlogRepository{/* ... */}public class LastPostCritera : ICriteria{/* ... */}public class CategorizedCritera : ICriteria{/* ... */}public class DatedCritera : ICriteria{/* ... */}

En esta implementacin crearamos un repositorio base que contendra los mtodos genricos de aadir, borrar y listar. Pero estos mtodos han sido declarados como protected, lo que repercutir en que no puedan ser invocados desde fuera del contexto de un repositorio.En cuanto repositorio, expondr una interfaz diferente al tpico CRUD (Create, Read, Update, Delete), y usando las funciones protegidas de la base realizara tareas especficas de gestin de la informacin. Adems, los listados y filtros se podrn realizar con un patrn Specification, ocultando en realidad el cdigo especfico y necesario para realizar la comunicacin con la base de datos.Y en definitiva, as conseguiramos un cdigo testeable, y desacoplar el acceso a los datos, del resto de la aplicacin.

Ejemplo De Utilizacion De Entity Framework-Modelo en base de datos

Lo primero que necesitamos como prerequisito es tener una base de datos, en mi caso una en SQL Server con la siguiente estructura:-Creando nuestro Modelo conceptualLo primero es abrir la mejor IDE del mundo, nuestro Visual Studio 2010 . Archivo, nuevo, proyecto y seleccionamos un proyecto del tipo aplicacin de Consola. Ahora bien, algo que se debe tener en cuenta antes de seguir, es que un modelo de Entity Framework es n elemento y NO un tipo de proyecto, por esto el siguiente paso sera agregar un nuevo elemento a nuestro proyecto de Consola, Click derecho, agregar, nuevo elemento, en la categora Data seleccionamos el tipo ADO.NET Entity Data Model:

Al pulsar Add, nos saldr un asistente de conexin. En la primera se nos da la opcin de crear un modelo conceptual a partir de un modelo de base de datos, y la otra crear un modelo vaco que luego podremos enviar a una base de datos, esto es lo que se conoce como Model First [no lo cubriremos en esta entrada]. la tcnica que usaremos en esta entrada se conoce como Database First.

En esta ventana especificamos la conexin a la base de datos donde estar nuestro modelo fsico, en mi caso quedara as:

Pulsamos ok y terminamos de configurar la creacin del EDMX.

Como vemos, el wizard ya nos ha proporcionado un nombre para el Entity connection y ademas no pregunta si deseamos incluir el Usuario y la contrasea de la conexin la cadena de conexin, podramos (por seguridad) dejarla por separado en el mismo archivo de configuracin ENCRIPTADA, pero en este caso a manera de ejemplo le diremos que si incluya esta informacin y pulsaremos siguiente.El Siguiente y ultimo paso es seleccionar que elementos de nuestro modelo fsico deseamos traer a nuestro modelo conceptual, se nos dan las opciones de Pluralizar o singularizar estos elementos, por lo general los trabajo de modo Singular desde que estn en la base de datos. Otra opcin que nos da es de incluir las llaves forneas en nuestro modelo y dar un nombre al espacio de nombres del modelo:

Una vez pulsamos finish veremos una caracterstica muy buena de Visual Studio 2010, el Entity Model Designer con las entidades que se han creado a partir de el modelo fsico que tenamos en la base de datos. y ademas de este, Visual Studio 2010 integra otra fascinante herramienta que nos facilita el trabajo en proyectos con muchas entidades, el Model Browser, se vera algo como:

- Explorando nuestro Modelo ConceptualAntes de continuar seria bueno fijarnos en ciertas cosillas, la primera que podemos notar es que Entity Framework nos ha agregado automticamente un archivo de configuracin y en su interior nos ha agregado un Connection String con una forma muy peculiar, algo como:

1. add name="EFDemoEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string="data source=.;2. initial catalog=EFDemo;user id=sa;password=****;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient"Si nos fijamos detenidamente vemos que en esta se define varios atributos, el primero y muy importante es el de metadata quien es el que define de que se compondr nuestro edmx, por supuesto de los tres archivos XML de los que hablamos en el post anterior (CSDL, SSDL y MSL), El siguiente atributo es el proveedor especifico con el que realizamos esta conexin (en mi caso es el SQLClient), el Servidor donde se encuentra la BD, la BD, el usuario y contrasea, la propiedad multipleactiveresultsets que nos indica si se pueden asociar varios conjuntos de resultados activos a la conexin asociada. y por ultimo tenemos el providerName que como ya habamos dicho en el post anterior el provider de Entity Framework se llama EntityClient. Otro aspecto importante a resaltar es que se ha agregado una referencia al ensamblado System.Data.Entity.

- Consumiendo nuestro Modelo Conceptual:Ahora que tenemos un poco mas claro el porque de los estragos que ha causado nuestro modelo en la apariencia de la solucin, podemos empezar a picar cdigo.En el mtodo main de nuestra app agregaremos una sentencia using (porque es auto-administrable ,etc, etc) y dentro de este creamos una instancia de nuestro modelo, as1. class Program2. {3. static void Main(string[] args)4. {a. using (EFDemoEntities context = new EFDemoEntities())b. {

c. }5. }6. }-Agregando datos con Entity Framework:Como dije en el primer post de esta serie, Entity Framework nos ahorra el tener que mapear a mano nuestras entidades a entidades de dominio, y expone automticamente muchos mtodos que ayudan a las operaciones CRUD.Para agregar un elemento a la entidad Pais, debemos crear un objeto de este tipo, agregarlo al contexto y guardar los cambios, as:

1. class Program2. {3. static void Main(string[] args)4. {a. using (EFDemoEntities context = new EFDemoEntities())b. {c. context.Pais.AddObject(new Pais{Nombre = "Colombia"});d. context.SaveChanges();e. }5. }6. }Entity Framework detecta si un campo es Autonumerico, es por esto que NO es necesario setearle un valor numrico a la propiedad Id.Ahora bien si quisiramos agregar un objeto HIJO es decir, una ciudad, podemos usar las propiedades de navegacin que nos da Entity Framework cuando detecta llaves forneas, as que seria cuestin de definir un valor a esta propiedad, as:1. class Program2. {3. static void Main(string[] args)4. {a. using (EFDemoEntities context = new EFDemoEntities())b. {c. Pais pais = new Pais { Nombre = "Bolivia" };d. Ciudad ciudad = new Ciudad{Nombre = "La Paz"};e. pais.Ciudad.Add(ciudad);f. context.Pais.AddObject(pais);g. context.SaveChanges();h. }5. }6. }-Eliminando datos con Entity Framework:Para eliminar un dato con Entity Framework, es necesario primero recuperarlo y luego si eliminarlo, algo as:1. class Program2. {3. static void Main(string[] args)4. {a. using (EFDemoEntities context = new EFDemoEntities())b. {c. Pais pais = (from p in context.Paisi. where p.Nombre == "Colombia"ii. select p).FirstOrDefault();d. context.Pais.DeleteObject(pais);e. context.SaveChanges();f. }5. }6. }En el escenario anterior, eliminamos un objeto padre que no tenia hijos, es un escenario sencillo pero nos sirve para entender y/o conocer la sintaxis de Linq por ejemplo y nos sirve para notar ademas, que siempre que se realice un cambio, si se desea ver reflejado en base de datos es necesario acudir al mtodo SaveChanges().Un escenario como el del segundo objeto que agregamos, que tiene un hijo (Pas Ciudad) se requiere eliminar todos sus hijos y luego si finalmente el Padre, de lo contrario obtendremos una excepcin. Otra alternativa, es habilitar la eliminacin en cascada, se puede hacer directamente sobe la relacin de las tablas en la base de datos o evaluar lo que en esta liga se propone.

- Editando datos con Entity Framework:Para editar un elemento, se sigue un procedimiento similar al que seguimos para eliminarlo, lo recuperamos, modificamos la propiedad que deseamos y SIN AGREGARLO al contexto, guardamos los cambios, as:

1. static void Main(string[] args)2. {a. using (EFDemoEntities context = new EFDemoEntities ())b. {c. Pais pais = (from p in context.Paisi. where p.Nombre == "Colombia"ii. select p).FirstOrDefault();d. pais.Nombre = "ColombiaEditada";e. context.SaveChanges();f. }3. }