public int Count(EntityQuery2 query) { var em = _domainService.Domain.Entities[query.Entity]; SqlTable main = new SqlTable(em.Name); var select = new SqlSelect(main, new SqlColumn("ID", main)); select.Count = true; if (query.AllProperties) { query.Properties = em.Properties.Select(p => p.Name).ToList(); } if (query.RelatedTo.Count > 0) { select.Distinct = true; } select.AddColumns(query.Properties.Where(p => !p.Equals("id", StringComparison.InvariantCultureIgnoreCase)).Select(p => new SqlColumn(em.Properties[p].Name, main)).ToArray()); if (query.SortBy == null) { query.SortBy = new Sorting("ID"); } if (!query.SortBy.IsRel) { var sortByColumn = new SqlColumn(query.SortBy.Property, main); select.OrderBy = new SqlOrderBy(sortByColumn, query.SortBy.Descending); } int id = 1; foreach (var rule in query.Rules) { AddRuleToSelect(em, select, main, rule); } foreach (var relto in query.RelatedTo) { if (relto.RelatedTo.Count > 0) { throw new NotImplementedException("Only one level of nested query (related) is allowed."); } var rel = em.GetRelation(relto.Entity, relto.Role); var other = rel.GetOther(em.Name); var relTable = new SqlTable(rel.Name, string.Format("tbl{0}", id++)); var otherTable = new SqlTable(other.Name, string.Format("tbl{0}", id++)); //TODO: code repetition with the includes logic! if (rel.Left.Name == em.Name) { select.AddJoin(relTable, new SqlColumn("LID", relTable), new SqlColumn("ID", main)); select.AddJoin(otherTable, new SqlColumn("RID", relTable), new SqlColumn("ID", otherTable)); } else { select.AddJoin(relTable, new SqlColumn("RID", relTable), new SqlColumn("ID", main)); select.AddJoin(otherTable, new SqlColumn("LID", relTable), new SqlColumn("ID", otherTable)); } foreach (var rule in relto.Rules) { AddRuleToSelect(other, select, otherTable, rule); } foreach (var rule in relto.RelationRules) { AddRuleToSelect(rel, select, relTable, rule); } } using (var ctx = _dbService.GetDatabaseContext(false)) { SqlCommand cmd = select.ToSqlCommand(ctx.Connection); int result = (int)cmd.ExecuteScalar(); return(result); } }
public IEnumerable <Entity> Search(EntityQuery2 query) { var em = _domainService.Domain.Entities[query.Entity]; SqlTable main = new SqlTable(em.Name); var select = new SqlSelect(main, new SqlColumn("iD", main)); if (query.AllProperties) { query.Properties = em.Properties.Select(p => p.Name).ToList(); } if (query.RelatedTo.Count > 0) { select.Distinct = true; } select.AddColumns(query.Properties.Where(p => !p.Equals("id", StringComparison.InvariantCultureIgnoreCase)).Select(p => new SqlColumn(em.Properties[p].Name, main)).ToArray()); if (query.SortBy == null) { query.SortBy = new Sorting("ID"); } if (!query.SortBy.IsRel) { var sortByColumn = new SqlColumn(query.SortBy.Property, main); select.OrderBy = new SqlOrderBy(sortByColumn, query.SortBy.Descending); } if (query.Paging != null) { var start = (query.Paging.Page - 1) * query.Paging.PageSize; select.Paging = new SqlPaging(start + 1, start + query.Paging.PageSize); } int id = 1; Dictionary <string, SqlSelect> additSearches = new Dictionary <string, SqlSelect>(); foreach (var inc in query.Includes) { var rel = em.GetRelation(inc.Entity, inc.Role); var relType = rel.TypeFor(em.Name); bool isLeft = rel.Left.Name == em.Name; var other = isLeft ? rel.Right : rel.Left; if (relType == RelationType.OneToOne || relType == RelationType.ManyToOne) { var relTable = new SqlTable(rel.Name, string.Format("tbl{0}", id++)); var entTable = new SqlTable(other.Name, string.Format("tbl{0}", id++)); if (isLeft) { select.AddJoin(relTable, new SqlColumn("LID", relTable), new SqlColumn("ID", main)); select.AddJoin(entTable, new SqlColumn("RID", relTable), new SqlColumn("ID", entTable)); } else { select.AddJoin(relTable, new SqlColumn("RID", relTable), new SqlColumn("ID", main)); select.AddJoin(entTable, new SqlColumn("LID", relTable), new SqlColumn("ID", entTable)); } select.AddColumns(rel.Properties.Select(p => new SqlColumn(p.Name, relTable)).ToArray()); select.AddColumns(other.Properties.Select(p => new SqlColumn(p.Name, entTable)).ToArray()); if (query.SortBy != null && query.SortBy.IsRel && query.SortBy.Role.Equals(rel.Role, StringComparison.InvariantCultureIgnoreCase) && query.SortBy.Entity.Equals(other.Name, StringComparison.InvariantCultureIgnoreCase)) { //TODO: sort by rel properties select.OrderBy = new SqlOrderBy(new SqlColumn(query.SortBy.Property, entTable), query.SortBy.Descending); } } else { var relTbl = new SqlTable(rel.Name, rel.Name); var s = new SqlSelect(relTbl, rel.Properties.Select(pm => new SqlColumn(pm.Name, relTbl)).ToArray()); var entTbl = new SqlTable(other.Name, other.Name); s.AddJoin(entTbl, new SqlColumn(isLeft ? "rid" : "lid", relTbl), new SqlColumn("id", entTbl), SqlJoinType.Inner); s.AddColumns(other.Properties.Select(pm => new SqlColumn(pm.Name, entTbl)).ToArray()); if (inc.SortBy == null) { inc.SortBy = new Sorting("ID"); } var incSortCol = s.Columns.Find(c => c.Name.Equals(inc.SortBy.Property, StringComparison.InvariantCultureIgnoreCase)); if (incSortCol != null) { s.OrderBy = new SqlOrderBy(incSortCol, inc.SortBy.Descending); } if (inc.Paging != null) { var start = (inc.Paging.Page - 1) * inc.Paging.PageSize; s.Paging = new SqlPaging(start + 1, start + inc.Paging.PageSize); } additSearches.Add(rel.Name, s); } } //TODO: group? foreach (var rule in query.Rules) { AddRuleToSelect(em, select, main, rule); } foreach (var relto in query.RelatedTo) { if (relto.RelatedTo.Count > 0) { throw new NotImplementedException("Only one level of nested query (related) is allowed."); } var rel = em.GetRelation(relto.Entity, relto.Role); var other = rel.GetOther(em.Name); var relTable = new SqlTable(rel.Name, string.Format("tbl{0}", id++)); var otherTable = new SqlTable(other.Name, string.Format("tbl{0}", id++)); //TODO: code repetition with the includes logic! if (rel.Left.Name == em.Name) { select.AddJoin(relTable, new SqlColumn("LID", relTable), new SqlColumn("ID", main)); select.AddJoin(otherTable, new SqlColumn("RID", relTable), new SqlColumn("ID", otherTable)); } else { select.AddJoin(relTable, new SqlColumn("RID", relTable), new SqlColumn("ID", main)); select.AddJoin(otherTable, new SqlColumn("LID", relTable), new SqlColumn("ID", otherTable)); } foreach (var rule in relto.Rules) { AddRuleToSelect(other, select, otherTable, rule); } foreach (var rule in relto.RelationRules) { AddRuleToSelect(rel, select, relTable, rule); } } using (var ctx = _dbService.GetDatabaseContext(false)) { List <Entity> result = new List <Entity>(); SqlCommand cmd = select.ToSqlCommand(ctx.Connection); using (var reader = cmd.ExecuteReader(System.Data.CommandBehavior.SequentialAccess)) { while (reader.Read()) { var e = new Entity(em.Name, reader.GetInt32(0)); var idx = 1; foreach (var prop in query.Properties) { var pm = em.Properties[prop]; if (pm.Is("id")) { continue; } e.Data[pm.Name] = GetValueFromReader(reader, pm, idx); idx++; } foreach (var inc in query.Includes) { var rel = em.GetRelation(inc.Entity, inc.Role); var relType = rel.TypeFor(em.Name); bool isLeft = rel.Left.Name == em.Name; var other = isLeft ? rel.Right : rel.Left; if (relType == RelationType.OneToOne || relType == RelationType.ManyToOne) { var relData = new Relation(rel.Role, new Entity(other.Name)); foreach (var prop in rel.Properties) { relData.Data[prop.Name] = GetValueFromReader(reader, prop, idx++); } foreach (var prop in other.Properties) { relData.Entity.Data[prop.Name] = GetValueFromReader(reader, prop, idx++); } if (!relData.Entity.Data.ContainsKey("id") || relData.Entity.Data["id"] == null) { continue; } relData.Entity.Id = relData.Entity.GetData <int>("id"); e.SetSingleRelation(relData); } } result.Add(e); } } if (result.Count > 0) { foreach (var kvp in additSearches) { var rel = em.Relations[kvp.Key]; var sel = kvp.Value; bool isLeft = em.Name == rel.Left.Name; var other = isLeft ? rel.Right : rel.Left; sel.Where.In(new SqlColumn(isLeft ? "lid" : "rid", sel.From), result.Select(e => e.Id)); SqlCommand getRelsCmd = sel.ToSqlCommand(ctx.Connection); using (var reader = getRelsCmd.ExecuteReader(System.Data.CommandBehavior.SequentialAccess)) { while (reader.Read()) { var idx = 0; Relation relationData = new Relation(rel.Role, new Entity(other.Name)); foreach (var prop in rel.Properties) { relationData.Data[prop.Name] = GetValueFromReader(reader, prop, idx++); } foreach (var prop in other.Properties) { relationData.Entity.Data[prop.Name] = GetValueFromReader(reader, prop, idx++); } relationData.Entity.Id = relationData.Entity.GetData <int>("id"); var mainId = isLeft ? relationData.GetData <int>("lid") : relationData.GetData <int>("rid"); result.Find(e => e.Id == mainId).AddManyRelation(relationData); } } } } ctx.Complete(); return(result); } }