MongoDB C# Driver Projection and Serialization - c#

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 ?

Related

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();

Automapper Finding Not Mapped properties

Using Automapper for a project, just mapping 2 objects to each other, nothing fancy. I must have something configured incorrectly because AutoMapper keeps saying that there are UnMapped Properties.
Here's the AutoMapper config.
var mapperConfig = new MapperConfiguration(cfg => {cfg.CreateMap<SrcObj, DestObj>()
.ForMember(dest => dest.Level, opt => opt.MapFrom(src => src.lvl));}
mapperConfig.AssertConfigurationIsValid();
SrcObj
public class SrcObj
{
public int Id { get; set; }
public int ParentNode { get; set; }
public string Controller { get; set; }
public string Action { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public bool? IsActive { get; set; }
public string AreaName { get; set; }
public int? DisplayOrder { get; set; }
public Int64 Type{ get; set; }
public int lvl { get; set; }
}
DestObj
public class DestObj
{
public int Id { get; set; }
public int ParentNode { get; set; }
public string Controller { get; set; }
public string Action { get; set; }
public string DisplayName { get; set; }
public string Description { get; set; }
public bool? IsActive { get; set; }
public string AreaName { get; set; }
public int? DisplayOrder { get; set; }
public Int64 Type{ get; set; }
public int Level { get; set; }
}
And the Implementation:
var items = await _context.Database.SqlQuery<SrcObj>($"EXEC spGenerateMenu {app1}").ToListAsync();
var rslt = _mapper.Map<DestObj>(items);
and the error:
{"\nUnmapped members were found. Review the types and members below.\nAdd a custom mapping expressio...}
The error actually lists every member of the DestObj. Not sure what I'm missing. probably something simple
Because your source is a List, you need to map it also to a List:
var rslt = _mapper.Map<List<DestObj>>(items);

C# linq to sql dynamic GroupJoin and Where

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.

Entity Framework Union and Except Query On Different Types

i want to User entity with Action's of Site Role's but point is ExtraAction entity,Action data will be filter by ExtraAction entity,
in ExtraAction entity:
if Type property == 1 this to be UNION to Action entity
if Type property == 0 this to be EXCEPT to Action entity
public class User
{
public int Id { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public ICollection<SiteRole> SiteRoles { get; set; }
public ICollection<ExtraAction> ExtraActions { get; set; }
}
public class SiteRole
{
public int Id { get; set; }
public string Description { get; set; }
public virtual ICollection<Action> Actions { get; set; }
public virtual ICollection<User> User { get; set; }
}
public class ExtraAction
{
public int Id { get; set; }
public int UserId { get; set; }
public int ActionId { get; set; }
public byte Type { get; set; }
public virtual Action Action { get; set; }
public virtual User User { get; set; }
}
public class Action
{
public int Id { get; set; }
public string Name { get; set; }
public string ActionName { get; set; }
public string ControllerName { get; set; }
public ICollection<SiteRole> SiteRoles { get; set; }
public virtual ICollection<ExtraAction> ExtraActions { get; set; }
}
finally my solution is below
var list = dbContext.Actions.Where(u =>
u.Roles.SelectMany(r => r.User).Any(su => su.Id == Id)).Select(row => new { Action = row }).
Union(dbContext.ExtraActions.Where(suea => suea.Type == 1 && suea.UserId == Id).Select(row => new { Action = row.Action })).
Except(dbContext.ExtraActions.Where(suea => suea.Type == 0 && suea.UserId == Id).Select(row => new { Action = row.Action })).ToList();

Categories