Para verificar si existe conexión a la base de datos desde nuestro contexto creado con Entity Framework, puedes hacerlo de la siguiente manera:
public bool VerificarConexión() {
using(var db = new MiEntities()) {
DbConnection conn = db.Database.Connection;
try {
//abrimos conexión, en caso de no existir dará excepción para caer en el catch
conn.Open();
return true;
} catch {
return false;
}
}
}
Igual te recuerdo que utilizar EntityFramework.Extended como Entity Framework nativo no las recomiendo cuando vas a modificar más de mil datos, mejor utiliza un procedimiento almacenado.
La ventaja que veo al utilizar EntityFramework.Extended es un aspecto de sintaxis ya que de esta manera evitamos hacer el recorrido de los elementos e ir modificando objeto por objeto, con esta librería es de una forma más sencilla para el programador.
Para el siguiente ejemplo, supongamos que tenemos una tabla llamada Persona, que debemos modificar la edad a 10 años de todas las personas de Nombre “Juan”. Seria de la siguiente manera:
using(MiEntity db= new MiEntity()){
//realizamos la modificación sin foreach, ni SaveChanges()
db.Persona.Where(d => d.Nombre=="Juan")
.Update(x => new Persona() { Edad = 10 });
}
De esta manera no necesitamos el método SaveChanges(), ya que Update lo hace internamente.
Existen varias formas de modificar varios elementos en conjunto por medio de Entity Framework.
Te mostrare como realizar una forma de cómo hacerlo a continuación. Teniendo una tabla llamada Persona, supongamos que debemos modificar la edad a 10 años de todas las personas de Nombre “Juan”. Seria de la siguiente manera:
using(MiEntity db= new MiEntity()){
//Obtenemos todos los Juanes
IQuearyable<Persona> lst = db.Persona.Where(d=>d.Nombre=='Juan');
//recorremos la lista
foreach(Persona oPersona in lst){
//asignamos la edad
oPersona.Edad=10;
}
//modificamos los datos en la base de datos
db.SaveChanges();
}
Cuando tengas la necesidad de editar más de mil filas en un proceso, mejor hazlo con un procedimiento almacenado (Stored procedure).
Las transacciones son útiles cuando hablamos de base de datos y debemos hacer muchas consultas en conjunto, ya que nos permiten realizar un retroceso en la manipulación de datos si una de las consultas del conjunto falla.
Con Entity Framework es posible realizar transacciones, y no solo eso, sino que podemos tener el poder de realizar otras funciones distintas a manipulación de datos y decidir si fallan estas otras funciones aplicar un rollback.
A continuación te mostrare con un pequeño ejemplo.
Teniendo nuestro Entity Framework con el nombre MiEntity:
//creamos nuestro contexto
using (var db = new MiEntity())
{
//creamos el ámbito de la transacción
using (var dbContextTransaction = db.Database.BeginTransaction())
{
try
{
//una consulta
tabla oTabla = new tabla();
oTabla.campo="pato";
//agregamos el elemento
db.tabla.Add(oTabla);
//otra consulta
tabla2 oTabla2 = new tabla2();
oTabla2.campo="pato";
//agregamos otro elemento
db.tabla2.Add(oTabla2);
//guardamos en la base de datos
db.SaveChanges();
//hacemos algo extra a manipulación de datos
//como enviar un mail, suponiendo que regresa true si es exitoso
if (!EnviaUnMail())
{
//hacemos rollback si fallo el envio del mail
dbContextTransaction.Rollback();
}
//Hacemos commit de todos los datos
dbContextTransaction.Commit();
}
catch (Exception ex)
{
//hacemos rollback si hay excepción
dbContextTransaction.Rollback();
}
}
}
Para llenar de elementos un combobox existe diversas formas de hacerlo, y esta vez te mostrare como hacerlo a partir de una tabla mapeada en Entity Framework.
En el siguiente ejemplo, ya existiendo un Entity Framework en nuestro proyecto, hacemos la consulta deseada a la tabla con los filtros y ordenamiento deseado, y seleccionamos que campo será mostrado y que campo será el valor, llenamos nuestro combobox llamado cboCatalogo:
using (MiEntity db = new MiEntity()) {
//realizamos la consulta aplicando filtros y ordenamientos
//y convertimos a lista, esto ultimo es Importante
cboCatalogo.DataSource = db.tabla.Where(d => d.algo == 1).OrderBy(d=>d.nombre).ToList();
//campo que vera el usuario
cboCatalogo.DisplayMember = "nombre";
//campo que es el valor real
cboCatalogo.ValueMember = "id";
}
De esta manera tenemos más control con lo que deseamos mostrar, teniendo el poder de filtrar u ordenar nuestra consulta.
Cuando comenzamos a utilizar Entity Framework vemos la maravilla de LINQ al obtener los datos de manera relacional, organizarlos como si de Sql se tratara, pero nunca nos preguntamos que de distinto tiene cuando utilizamos IQueryable o IEnumerable, para explicarlo rápidamente nos basaremos en la siguiente tabla (suponiendo que su nombre es tabla, literal):
Cuando obtenemos los datos con IEnumerable de la siguiente forma:
IEnumerable<tabla> lst= from d in db.tabla
select d;
Si quisiéramos hacer un filtrado con una clausula where posterior a nuestra obtención de datos haríamos lo siguiente:
lst= lst.Where(d=>d.name=='Pedro');
Cuando utilizamos IEnumerable al llenar nuestro objeto con LINQlo que obtenemos son los datos de la tabla en nuestra colección es decir, que al aplicar el filtrado trabajamos directamente con un conjunto de datos en memoria al cual se le hace el where directamente. Esto ocasiona un mal performance cuando nuestra tabla tiene millones de datos ya que los tendríamos en memoria y posterior aplicaríamos el filtrado, esto es una mala practica que jamas se debe hacer.
Ahora veamos la diferencia con IQueryable:
IQueryable<tabla> lst= from d in db.tabla
select d;
//lo que obtiene IQueryable despues de la consulta es:
// select * from tabla
Ahora haremos el mismo filtro posterior a la consulta:
lst= lst.Where(d=>d.name=='Pedro');
//y aquí lo que hacemos es concatenarle:
select * from tabla where name='Pedro'
A diferencia de IEnumerable lo que tenemos en nuestro objeto IQueryablees la consulta SQL en sí, es decir tenemos algo como lo siguiente:
select * from tabla
where name='Pedro'
En conclusión si vamos a realizar filtrados dinámicos en un conjunto de datos se debe utilizar la interface IQueryable, es la forma correcta de aplicar manipulación a nuestra consulta antes de enviarla al servidor de base de datos. ¿Cuando se realizar el envió de la consulta al servidor por parte de IQueryable? Cuando hacemos uso de los datos es decir, cuando aplicamos un foreach o hacemos un ToList().
No es bueno para el rendimiento hacer este tipo de consultas ya que las tablas están en bases de datos distintas, pero muchas veces es necesario para el hecho de crear un reporte, o cuando se expande un sistema con nueva tecnología y al final el cliente desea un reporte combinado entre sus sistemas viejos y los nuevos, yo les mostrare una manera de poder lograr un join entre dos bases de datos distintas. El problema es el siguiente(es hipotético no necesariamente es real solo sirve para el ejemplo), tenemos una base de datos (BD1) con las ventas diarias guardadas en una tabla llamada ventas, se nos pide que sea mostrada la venta y a su lado los datos del domicilio de la tienda, pero nos damos cuenta que no contamos con esos datos, esos datos están en una tabla llamada tienda en una base de datos distinta (BD2), entonces necesitamos hacer un join entre las 2 bases de datos, y para hacerlo debemos tomar a consideración lo siguiente: Debemos evaluar cual tabla tiene menos registros ya que haremos primero la consulta sobre esa tabla primero y esos datos los tendremos en memoria. En este caso la tabla tienda es la que tiene menos datos (una tienda tiene muchas ventas así que el universo es menor por sentido común). Así que primero vamos por las tiendas de la siguiente forma:
//creamos nuestro contexto de la bd2 ya que ahi esta la tabla tienda
var db2= new entitiesTiendaDB();
//obtenemos las tiendas con una consulta simple de linq
var lstTiendas = from d in db2.tiendas.ToList()
select d;
Ahora que a tenemos las tiendas, de la siguiente manera hacemos el join con los datos que ya tenemos en la variable lstTienda:
//creamos el contexto de db1 el cual contiene la tabla ventas
var db = new entitiesVentasDB();
//teniendo un viewmodel llamado VentasViewModel el cual tenga solo los campos que necesitamos creamos la consulta
List<VentasViewModel> lst= from d in db.ventas.ToList()
//nuestra tienda se une por el campo codigTienda de lstTiendas y por el mismo campo en
//la tabla ventas
join t in lstTiendas on d.codigoTienda equals t.codidoTienda into un
//esto hace que sea un left join,
// si no ponen esto solo les regresara todo como inner join
from x in un.DefaultIfEmpty()
orderby t.nombreTienda
select new VentasViewModel
{
idTienda = (x!=null) ? x.id : 0, //como hicimos left join podría haber datos nullos y debemos evaluar
nombreTienda =(x!=null) ? x.nombre : "",
domicilioTienda =(x!=null) ? x.domicilio : "", //asi obtenemos el domicilio
codigo = (x!=null )? x.codigoTienda : "",
total= d.total //este viene en ventas así que accedo con d
subtotal=d.subtotal //igual que arriba
};
Es curioso para mi hacer esta entrada ya que cuando utilizamos un ORM de alguna manera casí nunca es necesario hacer consultas Sql para obtener o modificar datos de la base de datos, pero algunas veces nos es más fácil hacer la consulta ya sea por comodidad o ya sea un caso muy especial. Para no recurrir al famoso SqlCommand y sus derivados Entity Framework nos permite realizar una consulta en crudo de la siguiente manera:
//creamos nuestro objeto context
NuestroEntitie db= new NuestroEntitie();
//ExecuteSQLCommand invoca la consulta capturada
db.Database.ExecuteSqlCommand("update tabla set campo=1 where id>1000 and fecha>getdate()");