SQL: Count elements in a joined table while using group by - sql

Having written this question, C# + LinQ: get the total of elements of a related table, I am convinced I was not clear enough to get help (or at least I was not in the right direction for that), so I'll focus my question in a different way so to see if I get a start point.
My question was mainly about LinQ, and now I'll focus only on SQL and try to use a generalized way of asking, so please, don't mark it as duplicate again, because it is not.
Given the following tables, I need to list elements from TableA adding two columns counting how many elements from TableB and TableC has for each row:
TableA:
Column_name
Type
TableA_id
int
ForeignKey1
smallint
ForeignKey2
int
ForeignKey3
smallint
TableB:
Column_name
Type
TableB_id
int
ForeignKey1
smallint
ForeignKey2
smallint
ForeignKey3
int
TableC:
Column_name
Type
TableC_id
int
ForeignKey4
int
How tables are related:
For each TableA row, ForeignKey1 + ForeignKey2 + ForeignKey3 equals one row in TableB that needs to be count, in other words, I need to count the occurences of ForeignKey1 + ForeignKey2 + ForeignKey3 in TableB and display it as an extra "count" column in the TableA list.
Same, for each TableA row, I also need to count how many elements of the TableC belong to that row, taking into account that ForeignKey4 is the foreign key that links with TableB_id.
Saying it differently again, FK1 + FK2 + FK3 in TableA > one row in TableB, so TableA will have many related TableB rows and FK4 In TableC > one row in TableB, so in the end, one row in TableA will have x TableB and y TableC elements.
I hope I'm being clear now and get a SQL solution. Then I'll use it as a start point and try to translate it to LinQ.
This is what I was able to do so far:
With this next SQL query:
select a.tablea_id, a.foreignkey1, a.foreignkey2, a.foreignkey3, count(*) from TableA a
left join TableB b
on a.foreignkey1 = b.foreignkey1 and
a.foreignkey2 = b.foreignkey2 and
a.foreignkey3 = b.foreignkey3
group by a.tablea_id, a.foreignkey1, a.foreignkey2, a.foreignkey3
I am able to count elements from TableB for each TableA row, but I'm getting stuck with TableC part.
Edit 1: For #Svyatoslav Danyliv adding extra information so it's easier to help me:
Finca entity:
public partial class finca
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public finca()
{
this.ps = new HashSet<ps>();
this.orden_trabajo = new HashSet<orden_trabajo>();
}
public int finca_id { get; set; }
public string descripcion { get; set; }
public System.DateTime fecha_creacion { get; set; }
public int direccion_id { get; set; }
public bool disponible_contratacion { get; set; }
public short concesion_id { get; set; }
public string codigo_gis { get; set; }
public string numero_alternativo { get; set; }
public Nullable<System.DateTime> fecha_ultima_inspeccion { get; set; }
public Nullable<decimal> latitud { get; set; }
public Nullable<decimal> longitud { get; set; }
public int acometida_defecto_id { get; set; }
public short planificacion_defecto_id { get; set; }
public int oficina_mas_cercana_id { get; set; }
public int ruta_defecto_id { get; set; }
public virtual concesion concesion { get; set; }
public virtual direccion direccion { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<ps> ps { get; set; }
public virtual oficina oficina { get; set; }
public virtual planificacion planificacion { get; set; }
public virtual ruta ruta { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<orden_trabajo> orden_trabajo { get; set; }
public virtual acometida acometida { get; set; }
}
Contrato entity:
public partial class contrato
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public contrato()
{
this.contrato_clausula = new HashSet<contrato_clausula>();
this.contrato_file = new HashSet<contrato_file>();
this.contrato_tipo_facturacion = new HashSet<contrato_tipo_facturacion>();
this.incidencia_facturacion = new HashSet<incidencia_facturacion>();
this.reclamacion = new HashSet<reclamacion>();
this.deuda_externa = new HashSet<deuda_externa>();
this.contrato_ciclo = new HashSet<contrato_ciclo>();
this.contrato_campo_personalizado = new HashSet<contrato_campo_personalizado>();
this.ciclo_contrato_consumo_minimo = new HashSet<ciclo_contrato_consumo_minimo>();
this.contrato_historial = new HashSet<contrato_historial>();
this.convenio_contrato = new HashSet<convenio_contrato>();
this.convenio = new HashSet<convenio>();
this.orden_domiciliacion = new HashSet<orden_domiciliacion>();
this.contrato_coeficientes = new HashSet<contrato_coeficientes>();
this.ov_usuario_contrato = new HashSet<ov_usuario_contrato>();
this.sac_gestion = new HashSet<sac_gestion>();
this.expediente_morosidad = new HashSet<expediente_morosidad>();
this.contrato_tipo_contrato = new HashSet<contrato_tipo_contrato>();
this.adeudo_domiciliado = new HashSet<adeudo_domiciliado>();
this.contrato_tarjeta_bancaria = new HashSet<contrato_tarjeta_bancaria>();
this.contrato_estado_morosidad = new HashSet<contrato_estado_morosidad>();
this.contrato_cambio_email = new HashSet<contrato_cambio_email>();
this.ov_usuario_solicitud_cuenta = new HashSet<ov_usuario_solicitud_cuenta>();
this.cobro = new HashSet<cobro>();
this.devolucion_saldo = new HashSet<devolucion_saldo>();
this.contrato_consumo_historico_facturado = new HashSet<contrato_consumo_historico_facturado>();
this.notificacion_cobro_ventanilla = new HashSet<notificacion_cobro_ventanilla>();
this.grupo_gestor_cobro_contrato = new HashSet<grupo_gestor_cobro_contrato>();
this.tarjeta_bancaria_operacion = new HashSet<tarjeta_bancaria_operacion>();
this.factura = new HashSet<factura>();
this.orden_trabajo = new HashSet<orden_trabajo>();
this.grupo_gestor_cobro_contrato1 = new HashSet<grupo_gestor_cobro_contrato>();
}
public int contrato_id { get; set; }
public short tipo_contrato_id { get; set; }
public int ps_id { get; set; }
public int cliente_id { get; set; }
public short estado_contrato_idx { get; set; }
public Nullable<decimal> importe_fianza { get; set; }
public short idioma_comunicacion_id { get; set; }
public Nullable<int> direccion_emision_id { get; set; }
public string email_emision { get; set; }
public System.DateTime fecha_alta { get; set; }
public System.DateTime fecha_alta_solicitud { get; set; }
public Nullable<System.DateTime> fecha_baja { get; set; }
public Nullable<System.DateTime> fecha_solicitud_baja { get; set; }
public Nullable<short> relacion_inmueble_alta_idx { get; set; }
public bool cortable { get; set; }
public Nullable<long> contrato_file_id { get; set; }
public Nullable<int> ultimo_estado_morosidad_id { get; set; }
public Nullable<decimal> importe_pendiente_afavor { get; set; }
public Nullable<short> canal_cobro_idx { get; set; }
public Nullable<int> cliente_apoderado_alta_id { get; set; }
public Nullable<int> cliente_baja_id { get; set; }
public string referencia { get; set; }
public string observaciones { get; set; }
public bool excluir_facturacion_periodica { get; set; }
public Nullable<int> tipo_autorizado_baja_id { get; set; }
public Nullable<long> fichero_baja_id { get; set; }
public string observaciones_baja { get; set; }
public Nullable<System.DateTime> fecha_baja_prevista { get; set; }
public Nullable<bool> acepta_informacion_comercial { get; set; }
public bool exento_recargos { get; set; }
public int forma_envio_factura_id { get; set; }
public string aviso_al_lector { get; set; }
public Nullable<short> tipo_calibre_contratado_id { get; set; }
public Nullable<short> tipo_entidad_face_idx { get; set; }
public Nullable<int> oficina_contable_fe_id { get; set; }
public Nullable<int> organo_gestor_fe_id { get; set; }
public Nullable<int> unidad_tramitadora_fe_id { get; set; }
public Nullable<int> organo_proponente_fe_id { get; set; }
public short num_descargas_contrato_api { get; set; }
public bool gran_consumidor { get; set; }
public virtual cliente cliente { get; set; }
public virtual idioma idioma { get; set; }
public virtual direccion direccion { get; set; }
public virtual tipo_contrato tipo_contrato { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<contrato_clausula> contrato_clausula { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<contrato_file> contrato_file { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<contrato_tipo_facturacion> contrato_tipo_facturacion { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<incidencia_facturacion> incidencia_facturacion { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<reclamacion> reclamacion { get; set; }
public virtual cliente cliente_apoderado_alta { get; set; }
public virtual cliente cliente_baja { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<deuda_externa> deuda_externa { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<contrato_ciclo> contrato_ciclo { get; set; }
public virtual file file { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<contrato_campo_personalizado> contrato_campo_personalizado { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<ciclo_contrato_consumo_minimo> ciclo_contrato_consumo_minimo { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<contrato_historial> contrato_historial { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<convenio_contrato> convenio_contrato { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<convenio> convenio { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<orden_domiciliacion> orden_domiciliacion { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<contrato_coeficientes> contrato_coeficientes { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<ov_usuario_contrato> ov_usuario_contrato { get; set; }
public virtual file fichero_baja { get; set; }
public virtual tipo_autorizado_baja tipo_autorizado_baja { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<sac_gestion> sac_gestion { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<expediente_morosidad> expediente_morosidad { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<contrato_tipo_contrato> contrato_tipo_contrato { get; set; }
public virtual ps ps { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<adeudo_domiciliado> adeudo_domiciliado { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<contrato_tarjeta_bancaria> contrato_tarjeta_bancaria { get; set; }
public virtual contrato_estado_morosidad ultimo_contrato_estado_morosidad { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<contrato_estado_morosidad> contrato_estado_morosidad { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<contrato_cambio_email> contrato_cambio_email { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<ov_usuario_solicitud_cuenta> ov_usuario_solicitud_cuenta { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<cobro> cobro { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<devolucion_saldo> devolucion_saldo { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<contrato_consumo_historico_facturado> contrato_consumo_historico_facturado { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<notificacion_cobro_ventanilla> notificacion_cobro_ventanilla { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<grupo_gestor_cobro_contrato> grupo_gestor_cobro_contrato { get; set; }
public virtual forma_envio_factura forma_envio_factura { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<tarjeta_bancaria_operacion> tarjeta_bancaria_operacion { get; set; }
public virtual tipo_calibre tipo_calibre { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<factura> factura { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<orden_trabajo> orden_trabajo { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<grupo_gestor_cobro_contrato> grupo_gestor_cobro_contrato1 { get; set; }
}
Punto de suministro entity:
public partial class puntosuministroview
{
public int ps_id { get; set; }
public Nullable<int> contrato_id { get; set; }
public string razon_social { get; set; }
public string cliente_con_identificacion { get; set; }
public Nullable<System.DateTime> fecha_baja_contrato { get; set; }
public short concesion_id { get; set; }
public short planificacion_id { get; set; }
public Nullable<int> acometida_id { get; set; }
public string direccion_nombre_extendido { get; set; }
public Nullable<int> cliente_id { get; set; }
public string nombre_planificacion { get; set; }
public Nullable<short> ps_clasificacion_id { get; set; }
public short empresa_id { get; set; }
public string nombre_concesion { get; set; }
public short ps_activo_idx { get; set; }
public Nullable<int> ruta_id { get; set; }
public string ruta { get; set; }
public string identificacion { get; set; }
public Nullable<short> zona_id { get; set; }
public string nombre_zona { get; set; }
public string descripcion { get; set; }
public string codigo { get; set; }
}
From "puntosuministroview" concesion_id + planificacion_id + acometida_id identifies one Finca
From "contrato" ps_id identifies one puntodesuministroview.
What I need to a LinQ query where I list Fincas, but with two added columns where I count "puntosdesuministroview" and "contratos".

A row in tablea can have many entries in tableb, and a row in tableb can again have many entries in tablec. You want to show all tablea rows, each with their tableb and tablec counts.
In standard SQL you could simply join, aggregate and count as in the following query. The only thing to be aware of is that each tableb row appears multiple times in the joins to to them being linked to multiple tablec rows. So, count distinct tableb IDs to get the correct count.
select
a.*,
count(distinct b.tableb_id) as b_count,
count(c.tablec_id) as c_count
from tablea a
left outer join tableb b on b.foreignkey1 = a.foreignkey1
and b.foreignkey2 = a.foreignkey2
and b.foreignkey3 = a.foreignkey3
left outer join tablec c on c.foreignkey4 = b.tableb_id
group by a.tablea_id
order by a.tablea_id;
In SQL Server this is not possible, because this DBMS is not able to detect that grouping by the tablea's ID means it can show the complete row, as the ID uniqly identifies this data. (This is called functional dependency.) In SQL Server you can write above query, but the GROUP BY clause must contain all tablea columns. In the example:
group by a.tablea_id, a.foreignkey1, a.foreignkey2, a.foreignkey3
Another option is to do the aggregation step by step:
with c as
(
select foreignkey4, count(*) as cnt
from tablec
group by foreignkey4
)
, c_and_b as
(
select
b.foreignkey1, b.foreignkey2, b.foreignkey3,
count(*) as b_cnt,
coalesce(sum(c.cnt), 0) as c_cnt
from tableb b
left outer join c on c.foreignkey4 = b.tableb_id
group by b.foreignkey1, b.foreignkey2, b.foreignkey3
)
select
a.*,
coalesce(c_and_b.b_cnt, 0) as b_count,
coalesce(c_and_b.c_cnt, 0) as c_count
from tablea a
left outer join c_and_b on c_and_b.foreignkey1 = a.foreignkey1
and c_and_b.foreignkey2 = a.foreignkey2
and c_and_b.foreignkey3 = a.foreignkey3
order by a.tablea_id;
This latter query looks a lot more complicated than the first one. This is mainly because of the chain (a->b->c) where you want both the b and the c count. If b and c were independent from each other (say a = posts, b = upvotes, c = downvotes), then aggregating b and c and then joining those two results to table a would even be my preferred method. The query would still not look as slimlined as the first query, but would avoid other problems (mainly an unnecessarily big intermediate result plus aggregation problems when it's not only about counting, but about sums or averages).

If I understand what you are trying to do, this may help.
select a.tablea_id, a.foreignkey1, a.foreignkey2, a.foreignkey3, count(b.TableB_id) b_count, count(c.TableC_id) c_count
from
TableA a
left join TableB b on a.foreignkey1 = b.foreignkey1 and a.foreignkey2 = b.foreignkey2 and a.foreignkey3 = b.foreignkey3
left join TableC c on b.TableB_id = c.foreignkey4
group by a.tablea_id, a.foreignkey1, a.foreignkey2, a.foreignkey3

Related

Value not inserting in DateTime column using Entity Framework

I am trying to insert value in DateTime column with Entity Framework but it throwing error on db.SaveChanges() function. There are 2 DateTime columns but exception throwing for only one (entry.OT_Date) with no maximum detail.
var entry = new OT_Request_N();
entry.Emp_ID = StaticFunctions.WindowUserId;
entry.slno = db.OT_Request_N.Max(x=>x.slno)+1;
entry.OT_Date= otD;
entry.OT_Time_Req = hourRequest;
entry.Remarks_Req = sError.ReqRemarks;
entry.Req_Sent_On = DateTime.Now;
entry.Supervisor_ID = sError.ManagerID;
entry.Approve_Status = 0;
db.OT_Request_N.Add(entry);
db.SaveChanges();
Here is SQL table Design
Here is class generated in edmx file
public partial class OT_Request_N
{
public int slno { get; set; }
public string Emp_ID { get; set; }
public Nullable<System.DateTime> Req_Sent_On { get; set; }
public Nullable<int> OT_Time_Req { get; set; }
public string Supervisor_ID { get; set; }
public string Remarks_Req { get; set; }
public string Remarks_App { get; set; }
public Nullable<int> OT_Time_App { get; set; }
public string Approved_By { get; set; }
public Nullable<int> Approve_Status { get; set; }
public Nullable<System.DateTime> Approved_On { get; set; }
public Nullable<int> Operations { get; set; }
public string AltReq_ID { get; set; }
public Nullable<bool> Is_alert_sent { get; set; }
public Nullable<System.DateTime> OT_Date { get; set; }
}

Convert SQL query to Entity Framework which used AggregateFunctions and Where clause

How can I convert this query to Entity Framework?
SQL query:
SELECT Fullname, SUM(CoinCount+DiamondCount) AS GeneralPoint
FROM Students, Groups
WHERE Students.GroupId = Groups.Id AND Groups.Name = 'FSDA_1813_az'
GROUP BY Fullname
ORDER BY GeneralPoint
Entity:
public class Student
{
public int Id { get; set; }
public int GroupId { get; set; }
public string Fullname { get; set; }
public Nullable<int> DiamondCount { get; set; }
public Nullable<int> CoinCount { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
public string Education { get; set; }
public string Email { get; set; }
public System.DateTime Birthdate { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public Nullable<System.DateTime> LastVisited { get; set; }
public string Facebook { get; set; }
public string Linkedin { get; set; }
public string SocialMedia { get; set; }
public byte[] Photo { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Comment> Comments { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Exam> Exams { get; set; }
public virtual Group Group { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Point> Points { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<StudentHomework> StudentHomeworks { get; set; }
}
UserRepository:
public ICollection<Student> GetUsersForGroup(string group)
{
using (var db = new EFContext())
{
var temp = db.Students.Where(x => x.Group.Name == group).ToList();
// I have to sort students in group by their DiamondCount+CoinCount as new GeneralCount
temp = temp.OrderBy(x => );
}
}
I have to sort students for their general point (DiamondCount+CoinCount).
But I can't send LINQ query by using Entity Framework. How can I do this?
Not tested but it should work:
var result = db.Students.Where(x => x.Group.Name == group)
.GroupBy(g => g.Fullname)
.Select(i => new
{
FullName = i.Key,
GeneralPoint = i.Sum(s => s.DiamondCount + s.CoinCount)
})
.OrderBy(o => o.GeneralPoint)
.ToList();

Entity framework The column 'x' was specified multiple times for 'Filter1'

Developing Asp .Net MVC web application. Using Entity framework 6.1.1 and Visual Studio 2013.
Got this Linq:
Db.Distrule_contents.Where(x => x.distrule_id == DistruleId && x.Content.season_id.HasValue && x.Content.season.series_id == SeriesId).Select(x => x.Content).ToList();
and associated with DB tables classes:
[Table("distrule_content")]
public class Distrule_content
{
[Key,Column(Order=0)]
public int distrule_id { get; set; }
[Key, Column(Order = 1)]
[ForeignKey("Content")]
public string IDEC { get; set; }
public int status_id { get; set; }
public virtual Distrule Distrule { get; set; }
public virtual Content Content { get; set; }
public virtual Status Status { get; set; }
}
[Table("distrule")]
public class Distrule: CommonEntity
{
public string distrule_name { get; set; }
public DateTime? begin_date { get; set; }
public DateTime end_date { get; set; }
public int status_id { get; set; }
public int? minutes_to_tx { get; set; }
public string period_type { get; set; }
public bool? autoactivate_content { get; set; }
public virtual ICollection<Distrule_area> DistruleAreas { get; set; }
public virtual ICollection<Distrule_content> DistruleContent { get; set; }
public virtual ICollection<Distrule_georegion> DistruleGeoregion { get; set; }
public virtual Status status { get; set; }
}
[Table("content")]
public class Content
{
[Key]
public string IDEC { get; set; }
public DateTime? date_inserted { get; set; }
public DateTime? min_tx_date { get; set; }
public long? season_id { get; set; }
public int? episode_number { get; set; }
public string content_rus_name { get; set; }
public virtual Season season { get; set; }
}
[Table("status")]
public class Status: CommonEntity
{
public string status_name { get; set; }
}
As a Result receave this SQL Query:
SELECT
[Filter1].[distrule_id1] AS [distrule_id],
[Filter1].[IDEC1] AS [IDEC],
[Filter1].[date_inserted1] AS [date_inserted],
[Filter1].[min_tx_date1] AS [min_tx_date],
[Filter1].[season_id1] AS [season_id],
[Filter1].[episode_number1] AS [episode_number],
[Filter1].[content_rus_name1] AS [content_rus_name],
[Filter1].[season_id2] AS [season_id1]
FROM ( SELECT [Extent1].[distrule_id] AS [distrule_id1], [Extent1].[Distrule_Id] AS [distrule_id1], [Extent2].[IDEC] AS [IDEC1], [Extent2].[date_inserted] AS [date_inserted1], [Extent2].[min_tx_date] AS [min_tx_date1], [Extent2].[season_id] AS [season_id1], [Extent2].[episode_number] AS [episode_number1], [Extent2].[content_rus_name] AS [content_rus_name1], [Extent2].[season_Id] AS [season_id1], [Extent3].[series_id] AS [series_id1], [Extent3].[Series_Id] AS [series_id1], [Extent4].[season_id] AS [season_id2], [Extent4].[season_Id] AS [season_id2]
FROM [dbo].[distrule_content] AS [Extent1]
INNER JOIN [dbo].[content] AS [Extent2] ON [Extent1].[IDEC] = [Extent2].[IDEC]
LEFT OUTER JOIN [dbo].[Season] AS [Extent3] ON [Extent2].[season_Id] = [Extent3].[Id]
LEFT OUTER JOIN [dbo].[content] AS [Extent4] ON [Extent1].[IDEC] = [Extent4].[IDEC]
WHERE [Extent2].[season_id] IS NOT NULL
) AS [Filter1]
WHERE ([Filter1].[distrule_id1] = #p__linq__0) AND ([Filter1].[series_id1] = #p__linq__1)
And following error: The column 'distrule_id1' was specified multiple times for 'Filter1'.
What i am doing wrong?
update 2014-09-10
Solved after deep study EF navigation rules. Thx to chconger. Problem was in letting EF self realize where FK should be placed. So after adding everywhere ForeignKey attribute is worked fine.
Here how it looks now:
[Table("distrule_content")]
public class Distrule_content
{
[Key,Column(Order=0)]
public int distrule_id { get; set; }
[Key, Column(Order = 1)]
[ForeignKey("Content")]
public string IDEC { get; set; }
public int status_id { get; set; }
[ForeignKey("distrule_id")]
public virtual Distrule Distrule { get; set; }
[ForeignKey("IDEC")]
public virtual Content Content { get; set; }
[ForeignKey("status_id")]
public virtual Status Status { get; set; }
}
Couple of issues from what I can see.
1. You have a foreign key set above a mismatched string IDEC, instead
[Key, Column(Order = 1)]
[ForeignKey("Content")]
public virtual Content Content { get; set; }
2. You are missing a constructor with HashSets for your class Distrule
public Distrule()
{
DistruleAreas = new HashSet<DistruleArea>();
DistruleContents = new HashSet<DistruleContent>();
DistruleGeoregions = new HashSet<DistruleGeregion>();
}

How to create a history model of a specific model on MVC 4

I'm still new in creating Models using Entity Framework and MVC 4 Razor. I'm having a problem on how can I save a history of a model. How can I create a model that have a history on specific tables or fields ? For ex: If I wish to create a history on the changes on the school. Its still not clear to me how will I I create the model that saves history. How will be the triggering do I have to execute the save function on different models with the same data ?
Thank you so much in advance.
If anyone could be a simple example of model and a model history and how it is functioning, I'll be very grateful. Like a Sales or sales history.
Here's my code
One To Many
public class Child
{
[Key]
public int ChildID { get; set; }
[Required,Display(Name="Project Code")]
public string ProjectCode { get; set; }
public string Status { get; set; }
[DataType(DataType.Date)]
public DateTime StatusDate { get; set; }
public string FamilyName { get; set; }
public string GivenName { get; set; }
public string MiddleName { get; set; }
[DataType(DataType.Date)]
public DateTime Birthdate { get; set; }
public string Gender {get;set;}
public string Address { get; set; }
public string Section { get; set; }
public int SchoolLevelID { get; set; }
public int SchoolYearID { get; set; }
public int AreaID { get; set; }
public int SchoolID { get; set; }
public int GradeLevelID { get; set; }
//Foreign Key - One to Many
public virtual SchoolLevel SchoolLevel { get; set; }
public virtual SchoolYear SchoolYear { get; set; }
public virtual Area Area { get; set; }
public virtual School School { get; set; }
public virtual GradeLevel GradeLevel{get;set;}
//Child is foreign key at the table
public virtual ICollection<Guardian> Guardians { get; set; }
}
public class SchoolLevel
{
public int SchoolLevelID { get; set; }
public string SchoolLevelName { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class SchoolYear
{
public int SchoolYearID { get; set; }
public string SchoolYearName { get; set; }
public virtual ICollection<Child> Children{get;set;}
}
public class Area
{
public int AreaID{get;set;}
public string AreaName { get; set; }
public virtual ICollection<Child> Children{get;set;}
}
public class School
{
public int SchoolID { get; set; }
public string SchoolName{get;set;}
public virtual ICollection<Child> Children { get; set; }
}
public class GradeLevel
{
public int GradeLevelID{get;set;}
public string GradeLevelName { get; set; }
public virtual ICollection<Child> Children { get; set; }
}
public class ChildDbContext : DbContext
{
public DbSet<Child> Children { get; set; }
public DbSet<SchoolLevel> SchoolLevels { get; set; }
public DbSet<SchoolYear> SchoolYears { get; set; }
public DbSet<Area> Areas { get; set; }
public DbSet<School> Schools { get; set; }
public DbSet<GradeLevel> GradeLevels { get; set; }
public DbSet<Guardian> Guardians { get; set; }
}
You can use this approach: Create a History model. That contains 1 changeness like o log.
public class History
{
public int HistoryId { get; set; }
public int ModelType { get; set; } //it is ModelTypeEnum value.
public int ModelId { get; set; }
public string PropertyName { get; set; }
public string Propertyvalue {get;set;}
public DateTime ChangeDate { get; set; }
public int ChangedUserId { get; set; }
}
And Enum:
public enum ModelTypeEnum
{
Child =1,
SchoolLevel = 2,
//etc..
};
For example, when you edit 1 Child entity, give changed properties name and value, it's id, type and others (ChangeDate, ChangedUserId) to History and save histories. If 3 properties will change you should save 3 history entities. Then, you can load (filter) histories by ModelId, by ChangedUserId etc.

How to create a Shipping Order with AdventureWorks2012

I'm deploying a Adventure Cycle page where the people can order one of bikes. I want to create a Shipping Information include (Address 1, Address 2, City, Country, Zip/Postal, and State/Province). When click the Submit Order it will redirect to Complete page to inform User that order is successful.
Address model:
public partial class Address
{
public Address()
{
this.SalesOrderHeaders = new HashSet<SalesOrderHeader>();
this.SalesOrderHeaders1 = new HashSet<SalesOrderHeader>();
}
public int AddressID { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public Nullable<int> StateProvinceID { get; set; }
public string PostalCode { get; set; }
public System.Guid rowguid { get; set; }
public Nullable<System.DateTime> ModifiedDate { get; set; }
public virtual StateProvince StateProvince { get; set; }
public virtual ICollection<SalesOrderHeader> SalesOrderHeaders { get; set; }
public virtual ICollection<SalesOrderHeader> SalesOrderHeaders1 { get; set; }
}
Sales Order Header:
public partial class SalesOrderHeader
{
public SalesOrderHeader()
{
this.SalesOrderDetails = new HashSet<SalesOrderDetail>();
}
public int SalesOrderID { get; set; }
public byte RevisionNumber { get; set; }
public Nullable<System.DateTime> OrderDate { get; set; }
public Nullable<System.DateTime> DueDate { get; set; }
public Nullable<System.DateTime> ShipDate { get; set; }
public byte Status { get; set; }
public bool OnlineOrderFlag { get; set; }
public string SalesOrderNumber { get; set; }
public string PurchaseOrderNumber { get; set; }
public string AccountNumber { get; set; }
public int CustomerID { get; set; }
public Nullable<int> SalesPersonID { get; set; }
public Nullable<int> TerritoryID { get; set; }
public Nullable<int> BillToAddressID { get; set; }
public Nullable<int> ShipToAddressID { get; set; }
public int ShipMethodID { get; set; }
public Nullable<int> CreditCardID { get; set; }
Hope it will help you,
On your Complete View you must put the model Address to the redirect method of the Complet e form:
Like
`Public ActionResult SubmitOrder(Address address)
{
...
return View("Complete", address);
}
`
and
on your Complete View
first line must be
`
#Model namespace.Model.Address
//then you can use
#model.AddressLine1
#model.AddressLine2
#model.City
#model.PostalCode
#model.StateProvinceID // You will retrieve an Id here I guess but at least you will
//have your data. embedded in your razor code
`