c# - importancia - modelos didacticos en educacion fisica
Columna calculada en el código EF primero (5)
Necesito tener una columna en mi base de datos calculada por la base de datos como (suma de filas) - (suma de rowsb). Estoy usando el modelo de primer código para crear mi base de datos.
Esto es lo que quiero decir:
public class Income {
[Key]
public int UserID { get; set; }
public double inSum { get; set; }
}
public class Outcome {
[Key]
public int UserID { get; set; }
public double outSum { get; set; }
}
public class FirstTable {
[Key]
public int UserID { get; set; }
public double Sum { get; set; }
// This needs to be calculated by DB as
// ( Select sum(inSum) FROM Income WHERE UserID = this.UserID)
// - (Select sum(outSum) FROM Outcome WHERE UserID = this.UserID)
}
¿Cómo puedo lograr esto en EF CodeFirst?
Me encontré con esta pregunta al tratar de tener un primer modelo de código EF con una columna de cadena "Slug", se deriva de otra columna de cadena "Nombre". El enfoque que tomé fue ligeramente diferente pero funcionó bien, así que lo compartiré aquí.
private string _name;
public string Name
{
get { return _name; }
set
{
_slug = value.ToUrlSlug(); // the magic happens here
_name = value; // but don''t forget to set your name too!
}
}
public string Slug { get; private set; }
Lo bueno de este enfoque es que obtienes la generación de slug automática, sin exponer nunca el setter de babosas. El método .ToUrlSlug () no es la parte importante de esta publicación, puede usar cualquier cosa en su lugar para hacer el trabajo que necesita. ¡Aclamaciones!
Me gustaría hacerlo solo con un modelo de vista. Por ejemplo, en lugar de tener la clase FirstTable como una entidad db, ¿no sería mejor tener una clase de modelo de vista llamada FirstTable y luego tener una función que se utiliza para devolver esta clase que incluiría la suma calculada? Por ejemplo, tu clase sería:
public class FirstTable {
public int UserID { get; set; }
public double Sum { get; set; }
}
Y luego tendría una función a la que llama que devuelve la suma calculada:
public FirsTable GetNetSumByUserID(int UserId)
{
double income = dbcontext.Income.Where(g => g.UserID == UserId).Select(f => f.inSum);
double expenses = dbcontext.Outcome.Where(g => g.UserID == UserId).Select(f => f.outSum);
double sum = (income - expense);
FirstTable _FirsTable = new FirstTable{ UserID = UserId, Sum = sum};
return _FirstTable;
}
Básicamente lo mismo que una vista de SQL y como se menciona en @Linus, no creo que sea una buena idea mantener el valor calculado en la base de datos. Solo algunos pensamientos.
Puede crear columnas calculadas en las tablas de su base de datos. En el modelo EF solo anota las propiedades correspondientes con el atributo DatabaseGenerated
:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public double Summ { get; private set; }
O con un mapeo fluido
modelBuilder.Entity<Income>().Property(t => t.Summ)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)
Según lo sugerido por Matija Grcic y en un comentario, es una buena idea hacer que la propiedad sea private set
, porque probablemente nunca querrá establecerlo en el código de la aplicación. Entity Framework no tiene problemas con los setters privados.
Una forma es hacerlo con LINQ:
var userID = 1; // your ID
var income = dataContext.Income.First(i => i.UserID == userID);
var outcome = dataContext.Outcome.First(o => o.UserID == userID);
var summ = income.inSumm - outcome.outSumm;
Puede hacerlo dentro de su public class FirstTable
objeto POCO public class FirstTable
, pero yo no lo sugeriría, porque creo que no es un buen diseño.
Otra forma sería usar una vista SQL. Puede leer una vista como una tabla con Entity Framework. Y dentro del código de vista, puede hacer cálculos o lo que quiera. Solo crea una vista como
-- not tested
SELECT FirstTable.UserID, Income.inCome - Outcome.outCome
FROM FirstTable INNER JOIN Income
ON FirstTable.UserID = Income.UserID
INNER JOIN Outcome
ON FirstTable.UserID = Outcome.UserID
public string ChargePointText { get; set; }
public class FirstTable
{
[Key]
public int UserID { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public string Summ
{
get { return /* do your sum here */ }
private set { /* needed for EF */ }
}
}
Referencias