Automapper. Not obvious transformation - entity

I have the following scenario:
public class SourceEntity
{
public int ClientId { get; set; }
public string ClientName { get; set; }
public string ClientMultipleValues1 { get; set; }
public string ClientMultipleValues2 { get; set; }
}
public class DestinationDto
{
public int ClientId { get; set; }
public string ClientName { get; set; }
public List<string> list1 { get; set; }
public List<string> list2 { get; set; }
}
SourceEntity values:
ClientId|ClientName|ClientMultipleValues1 |ClientMultipleValues2
1 | Albert | aaaaa | bbbbbbb
1 | Albert | ccccc | ddddddd
2 | Roger | zzzzz | yyyyyyy
I want using automapper that DestinationDto has these values:
ClientId|ClientName| list1 | list2
1 | Albert |{ aaaaa, ccccc }|{ bbbbbbb, ddddddd }
2 | Roger |{ zzzzz } |{ yyyyyyy }
Is it possible to do it? I mean, ClientId and ClientName must have only one row and ClientMultipleValues1, ClientMultipleValues2 have to be transformed into a List to make it possible.
Thanks

Related

EF Core razor pages with Include, ThenInclude. Displaying string instead of Id

I have the models Client, Project, ClientComment, ProjectComment, ProjectStatus, RAGStatus, and Resource. I am displaying a table of client-related and project-related comments grouped by Client.
I need to add the related ProjectStatus, RAGStatus, and Resource to my table, but I have been unable to connect the additional entities in my Include/ThenInclude query.
The ProjectStatus, RAGStatus, and Resource are bound via ViewData/VieWBag in drop-down menus and therefore saving the respective Id (not the actual string) in the ClientComment, Project, and ProjectComment tables.
I have tried to create a ViewModel for the ProjectStatus, RAGStatus, and Resource, but I am unable to find the right combination of Include/ThenInclude to display all the information I need on my table.
The Client model:
public class Client
{
public int Id { get; set; }
public string ClientName { get; set; }
public bool IsActive { get; set; }
public ICollection<ClientComment> ClientComments { get; set; }
public ICollection<Project> Projects { get; set; }
}
The Project model:
public class Project
{
public int Id { get; set; }
public string ProjectName { get; set; }
public int ClientId { get; set; }
public Client Client { get; set; }
public int ProjectStatusId { get; set; }
public ProjectStatus ProjectStatus { get; set; }
public int ResourceId { get; set; }
public Resource Resource { get; set; }
public bool IsArchived { get; set; }
public ICollection<ProjectComment> ProjectComments { get; set; }
}
The ClientComment model:
public class ClientComment
{
public int Id { get; set; }
public int? ClientId { get; set; }
public Client Client { get; set; }
public int RAGStatusId { get; set; }
public RAGStatus RAGStatus { get; set; }
public string StatusComment { get; set; }
public string EscalationComment { get; set; }
public string GeneralComment { get; set; }
public double? EOQ { get; set; }
public DateTime LastUpdateDate { get; set; }
public ClientComment ()
{
this.LastUpdateDate = DateTime.UtcNow;
}
The ProjectComment model:
public class ProjectComment
{
public int Id { get; set; }
public int? ProjectId { get; set; }
public Project Project { get; set; }
public int RAGStatusId { get; set; }
public RAGStatus RAGStatus { get; set; }
public string StatusComment { get; set; }
public string EscalationComment { get; set; }
public string GeneralComment { get; set; }
public double? EOQ { get; set; }
public DateTime LastUpdateDate { get; set; }
public ProjectComment ()
{
this.LastUpdateDate = DateTime.UtcNow;
}
The ProjectStatus model:
public class ProjectStatus
{
public int Id { get; set; }
public string ProjectStatusName { get; set; }
public bool IsActive { get; set; }
public ICollection<Project> Projects { get; set; }
}
The RAGStatus model:
public class RAGStatus
{
public int Id { get; set; }
public string RAGStatusName { get; set; }
public ICollection<ClientComment> ClientComments { get; set; }
public ICollection<ProjectComment> ProjectComments { get; set; }
public bool IsActive { get; set; }
}
The Resource model:
public class Resource
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string LongName { get; set; }
public bool IsActive { get; set; }
public ICollection<Project> Projects { get; set; }
}
The ClientVM model:
public class ClientVM
{
public string ClientName { get; set; }
public int ClientId { get; set; }
public int ClientCommentId { get; set; }
public string ClientStatusComment { get; set; }
public int RAGStatusId { get; set; }
public List<ProjectVM> Projectlist { get; set; }
public List<RAGStatusVM> RAGStatuslist { get; set; }
}
The ProjectVM model:
public class ProjectVM
{
public int ProjectId { get; set; }
public string ProjectName { get; set; }
public string ProjectStatusComment { get; set; }
public int RAGStatusId { get; set; }
public int ProjectStatusId { get; set; }
public int ResourceId { get; set; }
}
The PageModel:
[BindProperty]
public List<ClientVM> ClientVMList { get; set; }
public List<ProjectVM> ProjectVMList { get; set; }
public List<ResourceVM> ResourceVMList { get; set; }
public List<ProjectStatusVM> ProjectstatusVMList { get; set; }
public List<RAGStatusVM> RAGstatusVMList { get; set; }
public async Task<IActionResult> OnGet()
{
var clientlist = await _context.Client
.Include(c => c.ClientComments)
.ThenInclude(cr => cr.RAGStatus)
.Include(c => c.Projects)
.ThenInclude(p => p.ProjectComments)
.ThenInclude(pr => pr.RAGStatus).ToListAsync();
ClientVMList = new List<ClientVM>();
foreach (var item in clientlist)
{
ClientVM clientVM = new ClientVM()
{
Projectlist = new List<ProjectVM>()
};
clientVM.ClientId = item.Id;
clientVM.ClientName = item.ClientName;
if (item.ClientComments != null && item.ClientComments.Any())
{
clientVM.ClientStatusComment = item.ClientComments.OrderByDescending(cc => cc.LastUpdateDate).First().StatusComment;
}
else
{
clientVM.ClientStatusComment = "No StatusComment";
}
foreach (var projectItem in item.Projects)
{
ProjectVM projectVM = new ProjectVM
{
ProjectId = projectItem.Id,
ProjectName = projectItem.ProjectName,
ProjectStatusId = projectItem.ProjectStatusId,
ResourceId = projectItem.ResourceId
};
if (projectItem.ProjectComments != null && projectItem.ProjectComments.Any())
{
projectVM.ProjectStatusComment = projectItem.ProjectComments.OrderByDescending(pc => pc.LastUpdateDate).First().StatusComment;
}
else
{
projectVM.ProjectStatusComment = "No StatusComment";
}
clientVM.Projectlist.Add(projectVM);
}
ClientVMList.Add(clientVM);
}
return Page();
}
Client1 | ClientStatusComment | RAGStatus | ResourceName
Project1 | ProjectStatusComment | RAGStatus | ResourceName | ProjectStatusName
Project2 | ProjectStatusComment | RAGStatus | ResourceName | ProjectStatusName
Client2 | ClientStatusComment | RAGStatus | ResourceName
Project1 | ProjectStatusComment | RAGStatus | ResourceName | ProjectStatusName
Project2 | ProjectStatusComment | RAGStatus | ResourceName | ProjectStatusName

AspNet Core Display multiple records as one row with multiple columns in table

I'm having trouble with table view.
I want my table to look like this one
Name | Test1 | Test2 | Test3
================================
Anna | 70 | 51 | 90
================================
Jack | 56 | 77 | 82
================================
Now I have
Name | Grade | Test |
================================
Anna | 70 | Test1 |
================================
Anna | 51 | Test2 |
================================
Anna | 90 | Test3 |
================================
Jack | 56 | Test1 |
================================
Jack | 77 | Test2 |
================================
Jack | 82 | Test3 |
================================
The number of tests is dynamic.
Is there any way to do this? Couldn't find anything.
Should I create another model? Or it could be solved by editing View?
Model
public class StudentsWork
{
[Key]
public int IdStudentsWork { get; set; }
public int? Grade { get; set; }
public DateTime? Date { get; set; }
public int Student_id { get; set; }
public int Course_id { get; set; }
public int Test_id { get; set; }
[ForeignKey("Student_id")]
public Student StudentId { get; set; }
[ForeignKey("Course_id")]
public Course CourseId { get; set; }
[ForeignKey("Test_id")]
public Test TestId { get; set; }
}
Controller
public async Task<IActionResult> Group(int? id,int id_group)
{
var group = await _context.StudentsWork
.Include(p => p.StudentId)
.ThenInclude(p => p.GroupId)
.Include(p => p.CourseId)
.Include(p => p.TestId)
.Where(c => c.Course_id == id && c.StudentId.Group_id == id_group)
.ToListAsync();
return View(group);
}
Any help would be greatly appreciated.
You can group by StudentId and select a dictionary for each group to get test name and grade :
var query = db.StudentsWork.Include(p => p.StudentId)
.Include(p => p.CourseId)
.Include(p => p.TestId)
.GroupBy(c => c.StudentId)
.Select(g => new
{
StudentName=g.Key.Name,
TestGrade = g.ToDictionary(t => t.TestId.Name, t => t.Grade)
});
var result = query.ToList();

EntityFramework Core 2 : One to Many mapping using filtered list

I have entities that look like this:
class Parent1
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Child> Children { get; set; }
}
class Parent2
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Child> Children { get; set; }
}
class Child
{
public int Id { get; set; }
public string Name { get; set; }
public string ParentType { get; set; }
public int ParentId { get; set; }
}
basically in my case I have a Child table that contains the reference to different type of parents, but only one at a time. I am unable to understand how to create a ModelBuilder mapping to address this.
when I use entity.HasMany(d => d.Children) I don't see a way to map it with ParentType = "Parent1" and ParentId = d.Id
is it even possible in the EFCore 2.X
Update 1:
I have a constraint that I cannot change my table design that looks like this on the child_table
------------------------------------------------
| Id | Name | Parent_Type | Parent_Id |
------------------------------------------------
| 1 | C1 | Parent1 | 1 |
| 2 | C2 | Parent2 | 1 |
| 2 | C3 | Parent2 | 1 |
| 2 | C4 | Parent1 | 1 |
| 2 | C5 | Parent2 | 1 |
------------------------------------------------
You have to add both parent entities to the child entity and make the foreign-keys nullable.
Adjust your child-model to look like this
public class Child
{
public int Id { get; set; }
public string Name { get; set; }
public Parent1 Parent1 { get; set; }
public int? ParentId1 { get; set; }
public Parent2 Parent2 { get; set; }
public int? ParentId2 { get; set; }
}
In you DbContext in the OnModelCreating(ModelBuilder modelBuilder) method, do the following
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Parent1>()
.HasMany(p => p.Children)
.WithOne(c => c.Parent1)
.HasForeignKey(c => c.ParentId1);
modelBuilder.Entity<Parent2>()
.HasMany(p => p.Children)
.WithOne(c => c.Parent2)
.HasForeignKey(c => c.ParentId2);
modelBuilder.Entity<Child>();
// more configuration
}
Now you can either have Parent1 or Parent2 or even both. In general your model doesn't make much sense like this but it would work. Maybe you need to rethink the model design you are trying to use.
You can find more samples on how to work with relationships in EF here.

Fetch Grouped data in ViewModel

I am having following data as::
(I/P)
UserID Name Date Amount
1 Rahul 2014-04-01 10
1 Rahul 2014-05-01 20
1 Rahul 2014-06-01 30
1 Rahul 2014-07-01 40
1 Rahul 2014-08-01 50
1 Rahul 2014-09-01 60
1 Rahul 2014-10-01 70
and I want My Output as ::
(O/P)
UserID Name First Second Third Fourth Fifth
1 Rahul (2014-04-01,10) (2014-05-01,20) (2014-06-01,30) (2014-07-01,40) (2014-08-01,50)
I am using LINQ query for this but how can i get my expected above output.
In SQL or in LINQ.
I have got answer of my own question,
sharing with others for future reference
1)
I have made two ViewModels as::
public class MonthViewModel
{
public DateTime MonthName { get; set; }
public decimal Amount { get; set; }
}
public class ParentViewModel
{
public long ID { get; set; }
public string Name { get; set; }
//For Months
public decimal FirstMonth { get; set; }
public decimal SecondMonth { get; set; }
public decimal ThirdMonth { get; set; }
public decimal FourthMonth { get; set; }
public decimal FifthMonth { get; set; }
public decimal SixthMonth { get; set; }
}
2) Then By getting Data in the format like ::
(I/P)
UserID Name Date Amount
1 Rahul 2014-04-01 10
1 Rahul 2014-05-01 20
1 Rahul 2014-06-01 30
1 Rahul 2014-07-01 40
1 Rahul 2014-08-01 50
1 Rahul 2014-09-01 60
1 Rahul 2014-10-01 70
I am using LINQ + Pivot functionality as ::
DateTime CurrentDate = Datetime.UtcNow;
var DetailsList = DataList
.GroupBy(x => new { x.ID, x.Name })
.Select(x => new ParentViewModel
{
ID=x.Key.ID,
Name=x.Key.Name,
FirstMonth=x.Where(y=>y.Month==CurrentDate).Sum(y=>y.Amount) ,
SecondMonth=x.Where(y=>y.Month==CurrentDate.AddMonths(-1)).Sum(y=>y.Amount) ,
ThirdMonth=x.Where(y=>y.Month==CurrentDate.AddMonths(-2)).Sum(y=>y.Amount) ,
FourthMonth=x.Where(y=>y.Month==CurrentDate.AddMonths(-3)).Sum(y=>y.Amount) ,
FifthMonth=x.Where(y=>y.Month==CurrentDate.AddMonths(-4)).Sum(y=>y.Amount) ,
}
).ToList();
Thats it.

How to validate a UserProfile at the begining of a Controller to show specific data

I have a UserProfile Model as the following:
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public string Position { get; set; }
public string Authority { get; set; }
public string Service { get; set; }
public string Area { get; set; }
public int IsWrite { get; set; }
}
the table data looks like the following:
UserID | UseName | Position | Authority | Service | Area | IsWrite
1 | Peter | HSK Manager | Svc-Ar | HSK | WA | 0
2 | Dorothy | Branch Manager| Ar | All | EA |1
3 |Mike | HSK Director | Svc | HSK | All | 0
4 | Roddel | HSK Data Entry | Svc | HSK | All | 1
5 | Susan| WA Data Entry |Ar | All | WA | 1
6 | Nancy| Facility COO | All | All | All | 0
7 | Allan | Food Branch Mananger | Svc-Ar | FSD | EA | 0
Users has many kinds of authority scope; for example: one has an authority upon a specific service, the other has an authority upon a specific area, and may a user has authority to view records upon a service and an area both. I want to make a logic for each List controller action to check the UserProfile authority and then list data considering the scope of authority for each user.
this is another model which its data depends on the authority of users called Projects:
public class Projects
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ProjectID { get; set; }
public string Service { get; set; }
public string Area { get; set; }
[Required]
[DisplayName("Project Name")]
public string ProjectName { get; set; }
[Required]
[DataType(DataType.Currency)]
[DisplayName("Contract Value")]
public double ContractValue { get; set; }
[Required]
[DisplayName ("Contract Total MP")]
public int ContractMP { get; set; }
[Editable(false)]
public int UserID { get; set; }
[DataType(DataType.DateTime )]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime EntryDateTime { get; set; }
}
I want to put a logic in the beginning of the Projects Controller 'Index' action to validate the user's authority; if it's "Svr" it will show only the data of his service, if his authority is "Ar" it will show only data of his Area only, if his Authority is "Svr-Ar" it will show data of his Service and Area only, and if his authority is "All" it will show all data.
I tried many ways to do this, I could not, and I am new to MVC. please help me. Regards.
May be you'd better try to use roles. Then you may simply check:
if(Roles.IsUserInRole("Ar"))
{
//Show data for role Ar
}
But you may do the same with your Authority field. Just make simple method:
public string GetUserAuthority(int UserID)
{
var user = db.UserProfile.Find(id);
return user.Authority;
}
or if you use Membership:
public string GetUserAuthority()
{
var user = Membership.GetUser(User.Identity.Name);
return user.Authority;
}
Then check in Controller Action:
if(GetUserAuthority() == "Ar")
{
//Show data for role Ar
}