A continuación con un ejemplo te muestro como es posible hacerlo:
EntityDB db= new EntityDB();
var lst = from d in db.tabla.ToList() //es importante hacerlo lista
select new TablaViewModel
{
id = d.id,
//campo es string por lo cual
//nuestra función delegada regresara igual string
campo = (new Func<string>(() => {
try {
//utilizamos if
if(d.alguncampo==1){
return "Activo";
}else{
return "Inactivo";
}
}
catch {
//si ocurre un error
return "Error";
}
}
)
)()
};
De esta manera podemos manipular la información para lograr el resultado deseado.
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.
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();
}
}
}
En este video describo cómo es posible estar verificando si el usuario sigue teniendo la sesión en un sistema web.
Muchas veces nuestra sesión ha terminado por inactividad, y esta logística te servirá para tomar una decisión, si mandar al usuario a la pantalla de autentificación o simplemente mostrarle un mensaje de que su sesión expiro.
Ahora ya podrás ser capaz de detectar si la sesión ha terminado sin necesidad de que el usuario se entere hasta que de clic en algún elemento de tu pagina.
Para regresar un arreglo anónimo u objeto anónimo con formato JSON a través de un controller en MVC .Net, por ejemplo la lista de algún catalogo que no se necesite llenar con alguna tabla de base de datos, o una lista de años, meses o días, tenemos que hacerlo de la siguiente manera:
public JsonResult Metodo()
{
return Json(new[] { new { Id = 1, Nombre = "Dato 1"},new { Id=2, Nombre="Dato 2"}
}, JsonRequestBehavior.AllowGet);
//JsonRequestBehavior.AllowGet es opcional si nuestro método permitirá ser llamado por Get
}
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().
Para poder cachar excepciones dentro de una consulta LINQ y poder manipular el error para que no truene la consulta en si misma debemos hacer uso de Lambda, esto es útil cuando nuestra base de datos puede presentar inconsistencias las cuales pueden ocasionar una excepción en ciertos casos, y podemos evitarlo de la siguiente forma:
EntityDB db= new EntityDB();
var lst = from d in db.tabla.ToList() //es importante hacerlo lista
select new TablaViewModel
{
id = d.id,
//campo es string por lo cual
//nuestra función delegada regresara igual string
campo = (new Func<string>(() => {
try {
// suponiendo que exista una referencia
// a una tabla secundaria la cual no siempre exista
// lo cual puede ocasionar una excepción
// de esta manera lo podemos manipular
return d.tablaSecundaria.campo2;
}
catch { return "No existe"; }
}
)
)()
};
De esta manera nuestra consulta no tronara y podemos darle un resultado a la vista donde mostraremos nuestros datos.
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
};
Para llenar un SelectList manualmente y poder ser utilizado en nuestro DropDownList (o lo que sea) lo podemos hacer de la siguiente manera:
//creamos una lista tipo SelectListItem
List<SelectListItem> lst = new List<SelectListItem>();
//De la siguiente manera llenamos manualmente,
//Siendo el campo Text lo que ve el usuario y
//el campo Value lo que en realidad vale nuestro valor
lst.Add(new SelectListItem() { Text = "Pato", Value = "1" });
lst.Add(new SelectListItem() { Text = "Perro", Value = "2" });
lst.Add(new SelectListItem() { Text = "Pollo", Value = "3" });
lst.Add(new SelectListItem() { Text = "Gato", Value = "4" });
//Agregamos la lista a nuestro SelectList
SelectList miSL = new SelectList(lst, "Value", "Text");