C# linq to sql dynamic GroupJoin and Where - c#

The client application on the search form, a large number of text fields and lists. When sending data to the server, the data object is serialized to JSON. On the server in the JSON object desirealize to Person object:
public class Person
{
public Person()
{
}
[Group("Person", "persons")]
public string PersonName { get; set; }
[Group("Person", "persons")]
public string PersonLastName { get; set; }
[Group("Person", "persons")]
public string PersonPatronymic { get; set; }
[Group("Person", "persons_passport_data")]
public bool? PersonSex { get; set; }
[Group("Person", "persons_passport_data")]
public DateTime? PersonBirthday { get; set; }
[Group("Person", "persons_passport_data")]
public string PersonPassport { get; set; }
[Group("Person", "persons_passport_data")]
public string PersonPassportIssued { get; set; }
[Group("Person", "persons_passport_data")]
public int? PersonNation { get; set; }
[Group("PersonRegistration", "persons_registration")]
public int? PersonCitizenship { get; set; }
[Group("PersonRegistration", "persons_registration")]
public int? PersonCountry { get; set; }
[Group("PersonRegistration", "persons_registration")]
public int? PersonRegion { get; set; }
[Group("PersonRegistration", "persons_registration")]
public int? PersonDistrict { get; set; }
[Group("PersonRegistration", "persons_registration")]
public int? PersonCity { get; set; }
[Group("PersonRegistration", "persons_registration")]
public int? PersonQuarter { get; set; }
[Group("PersonActual", "persons_actual_residence")]
public int? PersonActualCountry { get; set; }
[Group("PersonActual", "persons_actual_residence")]
public int? PersonActualRegion { get; set; }
[Group("PersonActual", "persons_actual_residence")]
public int? PersonActualDistrict { get; set; }
[Group("PersonActual", "persons_actual_residence")]
public int? PersonActualQuarter { get; set; }
[Group("PersonActual", "persons_actual_residence")]
public int? PersonActualCity { get; set; }
}
Group attribute keeps the name of the group and the name of the table that contains the property.
public class GroupAttribute : Attribute
{
public GroupAttribute(string group, string table)
{
this.Group = group;
this.Table = table;
}
public string Group { get; set; }
public string Table { get; set; }
}
During the search for the persons responsible in the database method GetPersons. The commentary pointed out that it needs to be done.
public void GetPersons(Person person)
{
PropertyInfo[] PersonProperties = person.GetType().GetProperties();
var q = entity.persons
.Select(o => new {o.Id, o.PersonName, o.PersonLastName, o.PersonPatronymic})
foreach (var item in PersonProperties)
{
object value = item.GetValue(person);
string stringValue = value as string;
if (!string.IsNullOrEmpty(stringValue))
{
GroupAttribute group = item.GetCustomAttribute<GroupAttribute>();
/* Here, complete the join and logic
* For example:
*
q.GroupJoin(entity.*group.Table*, o => o.Id, i => i.PersonId, ... ?)
* .Where(w => w.*item.Name* == stringValue)
*/
}
}
}
I guess I need to use the ExpressionTree, but don't know where to start.

Related

MongoDB C# Driver Projection and Serialization

I have got a working code to join two mongo collections using $lookup.
[HttpGet("mongojoin")]
public IActionResult GetMongoJoinCollection([FromQuery(Name = "schoolId")] Guid schoolId)
{
var tabAssessmentCollection = mongoDatabase.GetCollection<TabAssessmentDocument>(MongoSettings.TabAssessmentDocumentName);
var tabComponentCollection =
mongoDatabase.GetCollection<TabComponentDocument>(MongoSettings.TabComponentDocumentName);
var resultMongo = tabAssessmentCollection
.Aggregate()
.Match(d => d.SchoolId.Equals(schoolId))
.Lookup(
foreignCollection: tabComponentCollection,
localField: ta => ta.ComponentId,
foreignField: tc => tc.TblId,
#as: (TabAssessmentDocument ta) => ta.Component
)
.Unwind(d => d.Component)
.ToList();
var resultList = new List<TabSubjectDocumentViewModel>();
foreach (var row in resultMongo)
{
resultList.Add(new TabSubjectDocumentViewModel()
{
Id = row["TblId"].AsGuid,
SchoolId = row["SchoolId"].AsGuid,
Name = row["Name"].AsString,
ShortName = row["ShortName"].AsString,
Active = row["Active"].AsNullableBoolean,
TabComponent = row["Component"]["Name"].AsString
});
}
return Ok(resultList);
}
}
public class TabSubjectDocumentViewModel
{
public Guid Id { get; set; }
public Guid? SchoolId { get; set; }
public string Name { get; set; }
public string ShortName { get; set; }
public bool? Active { get; set; }
public string TabComponent { get; set; }
}
public class TabAssessmentDocument
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public Guid TblId { get; set; }
public Guid? SchoolId { get; set; }
public string Name { get; set; }
public string ShortName { get; set; }
public Guid? ComponentId { get; set; }
public bool? Active { get; set; }
}
public class TabComponentDocument
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public Guid TblId { get; set; }
public Guid? SchoolId { get; set; }
public string Name { get; set; }
public string ShortName { get; set; }
public string ComponentType { get; set; }
public bool? Active { get; set; }
}
I tried using the Project method just after the .Unwind(d => d.Component), but, then I was not getting the $lookup collection data (TabComponent) in the Bsondocument. If I could Serialize this to a List, how should I be doing it ? Can anyone tell me how I should using the Projection and Serialization here ?

asp.net Core/ - Having trouble casting a linq query to a Dto

I have the following Linq statement that is currently not working.
var result = ClientDATARepository.AllIncluding(c => c.Jobs, c => c.ClientNotes, c => c.Suburb).Where(x => x.Id == id).Select(fetchedClient =>
new ClientDetailsDto {
Id = fetchedClient.Id,
ClientNo = fetchedClient.ClientNo,
Company = fetchedClient.Company,
IsWarrantyCompany = fetchedClient.IsWarrantyCompany,
CompanyName = fetchedClient.CompanyName,
ClientFirstName = fetchedClient.ClientFirstName,
ClientLastName = fetchedClient.ClientLastName,
MobilePhone = fetchedClient.MobilePhone,
DeActivated = fetchedClient.DateDeActivated.HasValue ? "true" : "false",
CreatedOn = EF.Property<DateTime>(fetchedClient, "CreatedOn").ToString("dd/MM/yyyy", CultureInfo.CurrentCulture),
ModifiedOn = EF.Property<DateTime>(fetchedClient, "ModifiedOn").ToString("dd/MM/yyyy", CultureInfo.CurrentCulture),
ClientNotes = fetchedClient.ClientNotes.Select(fetchedClientNote =>
new ClientNoteDto {
id = fetchedClientNote.Id,
Details = fetchedClientNote.Details,
}) as IQueryable<ClientNoteDto>
The initial method ClientDATARepository.AllIncluding is from the repository and is suppose to return the full details of a client:
public virtual IQueryable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = _context.Set<T>();
return includeProperties.Aggregate(query, (current, includeProperty) => current.Include(includeProperty));
}
Which should include all associated entities requested... which works to obtain a client however no ClientNotes are returned yet there are clientNotes in the database for the selected client.
The Dto I am trying to fill in is a follows:
public class ClientDetailsDto
{
public ClientDetailsDto()
{
}
[Key]
public int Id { get; set; }
public string ClientNo { get; set; }
public bool Company { get; set; }
public bool IsWarrantyCompany { set; get; }
public string CompanyName { get; set; }
public string ClientFirstName { get; set; }
public string ClientLastName { get; set; }
public string MobilePhone { get; set; }
public string DeActivated { get; set; }
public string CreatedOn { get; set; }
public string CreatedBy { get; set; }
public string ModifiedOn { get; set; }
public string ModifiedBy { get; set; }
public int SuburbId { get; set; }
public AddressDto Address { get; set; }
public IQueryable<ClientJobDto> ClientJobs { get; set; }
public IQueryable<ClientNoteDto> ClientNotes { get; set; }
}
ClientNoteDto is also presented for completeness:
public class ClientNoteDto
{
[Key]
public int id { get; set; }
public string Details { get; set; }
public string NoteType { get; set; }
public string CreatedOnDate { get; set; }
public string CreatedOnTime { get; set; }
public string CreatedBy { get; set; }
public string ModifiedOnDate { get; set; }
public string ModifiedOnTime { get; set; }
public string ModifiedBy { get; set; }
}
How do I get the IQueryable statement to return all the notes for this client as part of the result?

Including foreign key values into a DTO for a single record

It's been a while since I have done this, but I know there is an easy way to do this that I have forgotten. Below I have a class designed to populate a single record of a data object. But I cannot get the values from another table (related by foreign key) to populate using the lambda statement because I am missing something (the two values being pulled in from another table below can be seen as dto.LeaseName and dto.CarName). How should I write the lambda for the object dm?
public StationUnloadingLogDTO GetSingleRecordforLog(int Id)
{
StationUnloadingLogDTO dto = new StationUnloadingLogDTO();
StationUnloadingLog dm = new StationUnloadingLog();
dm = entity.StationUnloadingLog
.Where(x => x.Id == Id)
.FirstOrDefault();
dto.Id = dm.Id;
dto.DateLogged = dm.DateLogged;
dto.DriverName = dm.DriverName;
dto.TruckNumber = dm.TruckNumber;
dto.CarName = dm.Carrier.CarName;
dto.CarrierId = dm.CarrierId;
dto.SpecificGravity = dm.SpecificGravity;
dto.LactMeterOpen = dm.LactMeterOpen;
dto.LactMeterClose = dm.LactMeterClose;
dto.EstimatedBarrels = dm.EstimatedBarrels;
dto.TicketNumber = dm.TicketNumber;
dto.LeaseNumber = dm.LeaseNumber;
dto.LeaseName = dm.Company.CmpName;
dto.StationId = dm.StationId;
return dto;
}
Here are the related data classes
namespace Data.Models
{
public partial class Company
{
public Company()
{
StationUnloadingLog = new HashSet<StationUnloadingLog>();
}
public string CmpId { get; set; }
public string CmpName { get; set; }
public string CmpAddress1 { get; set; }
public string CmpAddress2 { get; set; }
public int? CmpCity { get; set; }
public string CmpZip { get; set; }
public string CmpPrimaryphone { get; set; }
public ICollection<StationUnloadingLog> StationUnloadingLog { get; set; }
}
public class StationUnloadingLogDTO
{
public int Id { get; set; }
public DateTime? DateLogged { get; set; }
public string DriverName { get; set; }
public string TruckNumber { get; set; }
public string CarrierId { get; set; }
public string CarName { get; set; }
public decimal? SpecificGravity { get; set; }
public decimal? LactMeterOpen { get; set; }
public decimal? LactMeterClose { get; set; }
public int? EstimatedBarrels { get; set; }
public string TicketNumber { get; set; }
public string LeaseName { get; set; }
public string LeaseNumber { get; set; }
public string StationId { get; set; }
}
public partial class StationUnloadingLog
{
public int Id { get; set; }
public DateTime? DateLogged { get; set; }
public string DriverName { get; set; }
public string TruckNumber { get; set; }
public string CarrierId { get; set; }
public decimal? SpecificGravity { get; set; }
public decimal? LactMeterOpen { get; set; }
public decimal? LactMeterClose { get; set; }
public int? EstimatedBarrels { get; set; }
public string TicketNumber { get; set; }
public string LeaseNumber { get; set; }
public string StationId { get; set; }
public Carrier Carrier { get; set; }
public Company Company { get; set; }
public Tractorprofile Tractorprofile { get; set; }
}
public partial class Carrier
{
public Carrier()
{
StationUnloadingLog = new HashSet<StationUnloadingLog>();
}
public string CarId { get; set; }
public string CarName { get; set; }
public string CarAddress1 { get; set; }
public string CarAddress2 { get; set; }
public int? CtyCode { get; set; }
public string CarZip { get; set; }
public string CarContact { get; set; }
public ICollection<StationUnloadingLog> StationUnloadingLog { get; set; }
}
You should query for your record with child entities like this.
dm = DbSet<StationUnloadingLog>
.Where(x => x.Id == Id).Include(x => x.Carrrier)
.FirstOrDefault();

Dapper c# Inner join

Hi Im trying do that query in dapper, but the list contatos return with the values null for my class Client, i don't know what i doing wrong. my class Clt_cadCliente is one Client has several contact (clt_cadContatos). Help please.
var lookup = new Dictionary<int, Clt_cadCliente>();
cn.Query<Clt_cadCliente, Clt_cadContatos, Clt_cadCliente>(#"
SELECT s.*, a.*
FROM Clt_cadCliente s
INNER JOIN Clt_cadContatos a ON s.IdCLiente = a.IdCliente ", (s, a) =>
{
Clt_cadCliente shop;
if (!lookup.TryGetValue(s.IdCliente, out shop))
{
lookup.Add(s.IdCliente, shop = s);
}
shop.Clt_cadContatos.Add(a);
return shop;
}, splitOn: "IdCliente").AsQueryable();
var resultList = lookup.Values;
Class:
public partial class Clt_cadCliente
{
public int IdCliente { get; set; }
public Nullable<int> IdClientePai { get; set; }
public string Codigo { get; set; }
public string Nome { get; set; }
public Nullable<System.DateTime> DataNasc { get; set; }
public string Sexo { get; set; }
public Nullable<int> IdEstCivil { get; set; }
public string CPF { get; set; }
public string RG { get; set; }
public Nullable<System.DateTime> DataAdm { get; set; }
public bool Pendencias { get; set; }
public string DescPendencia { get; set; }
public string Obs { get; set; }
public string PessoaFJ { get; set; }
public string NomeFantasia { get; set; }
public string CodDep { get; set; }
public string AtivoInativo { get; set; }
public bool Ativado { get; set; }
public Nullable<int> IdSitBloq { get; set; }
public Nullable<int> SitBloq { get; set; }
public string Profissao { get; set; }
public string Empresa { get; set; }
public string NomeEsposa { get; set; }
public Nullable<System.DateTime> NascEsposa { get; set; }
public Nullable<int> IdNaturezaPadrao { get; set; }
public Nullable<int> ViaCarteirinha { get; set; }
public Nullable<int> Casa { get; set; }
public Nullable<int> Renda { get; set; }
public Nullable<int> RendaComplementar { get; set; }
public string Naturalidade { get; set; }
public string Banco { get; set; }
public string Agencia { get; set; }
public string CidadeBanco { get; set; }
public bool VeiculoProprio { get; set; }
public Nullable<System.DateTime> DIB { get; set; }
public string Foto { get; set; }
public string Nbeneficio { get; set; }
public Nullable<bool> LiberarExame { get; set; }
public Nullable<System.DateTime> ValidadeExame { get; set; }
public Nullable<int> EnviaBoleto { get; set; }
public Nullable<int> IdUsuario { get; set; }
public Nullable<long> IdClienteGlobal { get; set; }
public virtual IList<Clt_cadContatos> Clt_cadContatos { get; set; }
}
Class 2:
public partial class Clt_cadContatos
{
public int IdContato { get; set; }
public string Nome { get; set; }
public string Telefone { get; set; }
public string Email { get; set; }
public bool AdicionarLista { get; set; }
public Nullable<int> IdCliente { get; set; }
}
I cannot test it of course, but I have a similar situation and if you don't insert, at least, the fields of the table Clt_cadContatos and in particular the name of the field IdCliente of this table, then the library cannot resolve the splitOn parameter
var lookup = new Dictionary<int, Clt_cadCliente>();
cn.Query<Clt_cadCliente, Clt_cadContatos, Clt_cadCliente>(#"
SELECT s.*, a.IdCliente, a.OtherField1, a.OtherField2, etc ....
FROM Clt_cadCliente s
INNER JOIN Clt_cadContatos a ON s.IdCLiente = a.IdCliente ", (s, a) =>
{
Clt_cadCliente shop;
if (!lookup.TryGetValue(s.IdCliente, out shop))
{
lookup.Add(s.IdCliente, shop = s);
}
shop.Clt_cadContatos.Add(a);
return shop;
}, splitOn: "IdCliente").AsQueryable();
var resultList = lookup.Values;
You are splitting on the wrong parameter. You need to split on IdContato.
The split on field tells Dapper where one entity ends and the next begins. If you select s.* followed by a.* you want to split into a second entity on the first field of the table a (I'm assuming that your sql tables resemble your classes.)

cannot implicitly convert type System.Collections.Generic.List<char>

I am trying to create a list of customer names that is fetched from a Json call but I get an error:
cannot implicitly convert type System.Collections.Generic.List<char>
to System.Collections.Generic.List<string>
I am using these 2 classes:
Customers:
namespace eko_app
{
static class Customers
{
public static List<CustomerResponse> GetCustomers(string customerURL)
{
List<CustomerResponse> customers = new List<CustomerResponse>();
try
{
var w = new WebClient();
var jsonData = string.Empty;
// make the select products call
jsonData = w.DownloadString(customerURL);
if (!string.IsNullOrEmpty(jsonData))
{
// deserialize the json to c# .net
var response = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(jsonData);
if (response != null)
{
customers = response.response;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return customers;
}
public class BusinessAssociate
{
public string business_associate_id { get; set; }
public string created_by { get; set; }
public DateTime created { get; set; }
public DateTime modified { get; set; }
public bool? deleted { get; set; }
public string business_id { get; set; }
public string identity_id { get; set; }
public string associate_type { get; set; }
public string name { get; set; }
}
public class Identity
{
public string identity_id { get; set; }
public string created_by { get; set; }
public DateTime created { get; set; }
public DateTime modified { get; set; }
public bool? deleted { get; set; }
public string name { get; set; }
public object identity_type { get; set; }
}
public class ChartOfAccount
{
public string chart_of_accounts_id { get; set; }
public DateTime created { get; set; }
public DateTime modified { get; set; }
public string created_by { get; set; }
public string deleted { get; set; }
public string account_id { get; set; }
public string account_name { get; set; }
public string business_id { get; set; }
public string account_category { get; set; }
public string accounts_groups_id { get; set; }
public string cash_equivalent { get; set; }
public string acc_category { get; set; }
public decimal? balance { get; set; }
public decimal? credit_balance { get; set; }
public decimal? debit_balance { get; set; }
public decimal? absolute_balance { get; set; }
public string balance_type { get; set; }
public decimal? raw_balance { get; set; }
public string extended_name { get; set; }
public string normal_balance_type { get; set; }
}
public class CustomerResponse
{
public BusinessAssociate BusinessAssociate { get; set; }
public Identity Identity { get; set; }
public ChartOfAccount ChartOfAccount { get; set; }
}
public class Messages
{
public string msgs { get; set; }
public string errs { get; set; }
}
public class RootObject
{
public List<CustomerResponse> response { get; set; }
public Messages messages { get; set; }
}
}
}
HomeForm:
private void GetCustomerNameList()
{
// get customers
customerURL = "https://eko-app.com/BusinessAssociate/list_associates/1/sessionId:" + sessionID + ".json";
var customers = Customers.GetCustomers(customerURL);
List<string> customerNames = new List<string>();
foreach (var c in customers)
{
customerNames = c.BusinessAssociate.name.ToList(); <--------error thrown here
}
}
The error is thrown at customerNames = c.BusinessAssociate.name.ToList(); on the HomeForm.
What am I doing wrong in creating a list of customer names?
I think you wanted to add all Customer.BusinessAssociate names to list:
foreach (var c in customers)
{
customerNames.Add(c.BusinessAssociate.name);
}
What you originally written converted each name string to char list.
You're assigning a list of chars (string) into a list of strings.
Try something like this outside of the foreach loop:
customerNames = customers.Select(x => x.BusinessAssociate.name).ToList();
This also makes the initialization of cutomerNames redundant.
Instead of foreach use:
customerNames = customers.Select(c => c.BusinessAssociate.name).ToList();

Categories