Home > OS >  How to group columns by table name in LINQ Method Syntax in Table Relationships C# ASP .NET Entity F
How to group columns by table name in LINQ Method Syntax in Table Relationships C# ASP .NET Entity F

Time:04-06

I am new at C# ASP.Net Entity Framework . I am trying to build an API and I want to produce an output like this :

[
    {
        
        "userId": 1275,
        "username": "dmartin",
        "email": "[email protected]",
        "firstName": "Dan",
        "middleInitial": "",
        "lastName": "Martin",
        "isApproved": true,
        "lastActivityDate": "2012-10-05T12:23:24.253",
        "lastLoginDate": "2021-10-27T09:13:56.597",
        "lastPasswordChangedDate": "2020-07-29T16:06:41.863",
        "creationDate": "2010-04-07T22:51:14",
        "Iscinstance":[
            {
                "iscinstanceId": 236,
                "name": "ABA"
            }
        ],
        "UserProfile":[
            {
                "profileName": "",
                "address1": "",
                "directConnectPhone": "",
                "profileEmail": "",
                "profile": null
            }
        ]
    }
]

A have this classis created with table relationships :

User Table

[DataContract]
public partial class User
{
    [DataMember]
    public int UserId { get; set; }
    [DataMember]
    public string Username { get; set; }
    [DataMember]
    public string Email { get; set; }
    [DataMember]
    public bool IsApproved { get; set; }
    [DataMember]
    public DateTime? LastActivityDate { get; set; }
    [DataMember]
    public DateTime? LastLoginDate { get; set; }
    [DataMember]
    public DateTime? LastPasswordChangedDate { get; set; }
    [DataMember]
    public DateTime? CreationDate { get; set; }
    [DataMember]
    public string FirstName { get; set; }
    [DataMember]
    public string LastName { get; set; }
    [DataMember]
    public string MiddleInitial { get; set; }

    public virtual UserProfile Profile { get; set; }
    public virtual LinkUsersToIscinstance LinkUsersToIscinstances { get; set; }
    
}

UserProfile Table

[DataContract]
public partial class UserProfile
{
    public UserProfile()
    {
        LinkUsersToIscinstances = new HashSet<LinkUsersToIscinstance>();
        Users = new HashSet<User>();
    }
    [DataMember]
    public int ProfileId { get; set; }
    [DataMember]
    public string ProfileName { get; set; }
    [DataMember]
    public string Email { get; set; }
    [DataMember]
    public string DirectConnectPhone { get; set; }
    [DataMember]
    public string EmergencyContactNumber { get; set; }
    [DataMember]
    public string Address1 { get; set; }
    [DataMember]
    public string Address2 { get; set; }
    [DataMember]
    public string County { get; set; }
    [DataMember]
    public int State { get; set; }
    [DataMember]
    public string Zip { get; set; }
    [DataMember]
    public string EmergencyCell { get; set; }
    
    public virtual ICollection<LinkUsersToIscinstance> LinkUsersToIscinstances { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

LinkUsersToIscinstance Table

[DataContract(IsReference = true)]
public partial class LinkUsersToIscinstance
{
    public LinkUsersToIscinstance()
    {
        Users = new HashSet<User>();
    }
    public int LinkId { get; set; }
    [DataMember]
    public int IscinstanceId { get; set; }
    [DataMember]
    public int UserId { get; set; }

    public virtual UserProfile Profile { get; set; }
    public virtual Iscinstance Iscinstances { get; set; }
    public virtual ICollection<User> Users { get; set; }
}

Iscinstance Table

[DataContract]
public partial class Iscinstance
{
    public Iscinstance()
    {
        LinkUsersToIscinstances = new HashSet<LinkUsersToIscinstance>();
    }
    [DataMember]
    public int IscinstanceId { get; set; }
    [DataMember]
    public string Name { get; set; }

    public virtual ICollection<LinkUsersToIscinstance> LinkUsersToIscinstances { get; set; }
}

I also created a custom class but I think a wont be needing it, here it is :

[DataContract]
public class CustomClass
{
    [DataMember]
    public int IscinstanceId { get; set; }
    //[DataMember(Name = "ISCInstanceName")]
    [DataMember]
    public string? Name { get; set; }
    [DataMember]
    public int UserId { get; set; }
    [DataMember]
    public string? Username { get; set; }
    [DataMember]
    public string? Email { get; set; }
    [DataMember]
    public string? FirstName { get; set; }
    [DataMember]
    public string? MiddleInitial { get; set; }
    [DataMember]
    public string? LastName { get; set; }
    [DataMember]
    public bool IsApproved { get; set; }
    [DataMember]
    public DateTime? LastActivityDate { get; set; }
    [DataMember]
    public DateTime? LastLoginDate { get; set; }
    [DataMember]
    public DateTime? LastPasswordChangedDate { get; set; }
    [DataMember]
    public DateTime? CreationDate { get; set; }
    [DataMember]
    public string? ProfileName { get; internal set; }
    [DataMember]
    public string? Address1 { get; internal set; }
    [DataMember]
    public string? DirectConnectPhone { get; internal set; }
    [DataMember]
    public string? ProfileEmail { get; internal set; }
}

And this is my query :

 var customer = await _context.Users
                            .Where(c => c.UserId  == UserId && c.LastActivityDate > date && c.IsApproved == num)
                            .Include(c => c.Profile)
                            .Include(c => c.LinkUsersToIscinstances).ThenInclude(c => c.Iscinstances)
                            .OrderBy(c => c.LinkUsersToIscinstances.Iscinstances.Name).ThenBy(c => c.LastName).ThenBy(c => c.FirstName)
                            .Select(c => new CustomClass
                            {
                                IscinstanceId = c.LinkUsersToIscinstances.Iscinstances.IscinstanceId,
                                Name = c.LinkUsersToIscinstances.Iscinstances.Name,

                                UserId = c.UserId,
                                Username = c.Username,
                                Email = c.Email,
                                FirstName= c.FirstName,
                                MiddleInitial= c.MiddleInitial,
                                LastName= c.LastName,
                                IsApproved= c.IsApproved,
                                LastActivityDate= c.LastActivityDate,
                                LastLoginDate= c.LastLoginDate,
                                LastPasswordChangedDate= c.LastPasswordChangedDate,
                                CreationDate= c.CreationDate,

                                ProfileName = c.Profile.ProfileName,
                                ProfileEmail = c.Profile.Email,
                                DirectConnectPhone = c.Profile.DirectConnectPhone,
                                Address1 = c.Profile.Address1

                                })
                            .ToListAsync();

This is my current output

[
    {
        "iscinstanceId": 236,
        "name": "ABA",
        "userId": 1275,
        "username": "dmartin",
        "email": "[email protected]",
        "firstName": "Dan",
        "middleInitial": "",
        "lastName": "Martin",
        "isApproved": true,
        "lastActivityDate": "2012-10-05T12:23:24.253",
        "lastLoginDate": "2021-10-27T09:13:56.597",
        "lastPasswordChangedDate": "2020-07-29T16:06:41.863",
        "creationDate": "2010-04-07T22:51:14",
        "profileName": "",
        "address1": "",
        "directConnectPhone": "",
        "profileEmail": "",
        "profile": null
    }
]

Hoping anyone could help me :(

CodePudding user response:

From your backend code, it seems one User have one UserProfile and Iscinstance, but your expected json here is a List object:

"Iscinstance":[
        {
            "iscinstanceId": 236,
            "name": "ABA"
        }
    ],
    "UserProfile":[
        {
            "profileName": "",
            "address1": "",
            "directConnectPhone": "",
            "profileEmail": "",
            "profile": null
        }
    ]

If you actually want this type of json, you need change your CustomClass to:

public class CustomClass
{
    public int UserId { get; set; }
    public string? Username { get; set; }
    public string? Email { get; set; }
    public string? FirstName { get; set; }
    public string? MiddleInitial { get; set; }
    public string? LastName { get; set; }
    public bool IsApproved { get; set; }
    public DateTime? LastActivityDate { get; set; }
    public DateTime? LastLoginDate { get; set; }
    public DateTime? LastPasswordChangedDate { get; set; }
    public DateTime? CreationDate { get; set; }
    public List<dynamic>? Iscinstance { get; set; }
    public List<dynamic>? UserProfile { get; set; }
}

Controller:

    var customer = await _context.User
                .Where(c => c.UserId  == UserId && c.LastActivityDate > date && c.IsApproved == num)
                .Include(c => c.Profile)
                .Include(c => c.LinkUsersToIscinstances).ThenInclude(c => c.Iscinstances)
                .OrderBy(c => c.LinkUsersToIscinstances.Iscinstances.Name).ThenBy(c => c.LastName).ThenBy(c => c.FirstName)
                .Select(c => new TestModel
                {
                    UserId = c.UserId,
                    Username = c.Username,
                    Email = c.Email,
                    FirstName = c.FirstName,
                    MiddleInitial = c.MiddleInitial,
                    LastName = c.LastName,
                    IsApproved = c.IsApproved,
                    LastActivityDate = c.LastActivityDate,
                    LastLoginDate = c.LastLoginDate,
                    LastPasswordChangedDate = c.LastPasswordChangedDate,
                    CreationDate = c.CreationDate,
                    Iscinstance = new List<dynamic>() {
                        new {
                            IscinstanceId= c.LinkUsersToIscinstances.Iscinstances.IscinstanceId,
                            Name = c.LinkUsersToIscinstances.Iscinstances.Name
                        }
                    },
                    UserProfile = new List<dynamic> {
                        new {
                            ProfileName = c.Profile.ProfileName,
                            ProfileEmail = c.Profile.Email,
                            DirectConnectPhone = c.Profile.DirectConnectPhone,
                            Address1 = c.Profile.Address1
                        }
                    }
                })
                .ToListAsync();

CodePudding user response:

First, you need some classes to represent the expected json result :

public class UserModel
{
    public int UserId { get; set; }
    public string? Username { get; set; }
    public string? Email { get; set; }
    public string? FirstName { get; set; }
    public string? MiddleInitial { get; set; }
    public string? LastName { get; set; }
    public bool IsApproved { get; set; }
    public DateTime? LastActivityDate { get; set; }
    public DateTime? LastLoginDate { get; set; }
    public DateTime? LastPasswordChangedDate { get; set; }
    public DateTime? CreationDate { get; set; }
    public IEnumerable<IscinstanceModel> Iscinstance { get; set; }
    public IEnumerable<UserProfileModel> UserProfile { get; set; }
}

public class IscinstanceModel
{
    public int IscinstanceId { get; set; }
    public string? Name { get; set; }
}

public class UserProfileModel
{
    public string? ProfileName { get; set; }
    public string? Address1 { get; set; }
    public string? DirectConnectPhone { get; set; }
    public string? ProfilEmail { get; set; }
    public string? Profile { get; set; }
}

Then you can concert your entities to the api model. But two trouble.

First, the expected json has by user a list of iscinstance, but the entity user has a list of list of iscinstance. SelectMany help to flat to simple list.

Second, the expected json has by user a list of profile, but the entity has one profile. In this case, just encapsulate the profile in a collection.

Finaly :

var customers = await _context.Users
    .Where(c => c.UserId  == UserId && c.LastActivityDate > date && c.IsApproved == num)
    .Include(c => c.Profile)
    .Include(c => c.LinkUsersToIscinstances).ThenInclude(c => c.Iscinstances)
    .OrderBy(c => c.LinkUsersToIscinstances.Iscinstances.Name).ThenBy(c => c.LastName).ThenBy(c => c.FirstName)
    .Select(c => new UserModel
    {
        UserId = c.UserId,
        Username = c.Username,
        Email = c.Email,
        FirstName = c.FirstName,
        MiddleInitial = c.MiddleInitial,
        LastName = c.LastName,
        IsApproved = c.IsApproved,
        LastActivityDate = c.LastActivityDate,
        LastLoginDate = c.LastLoginDate,
        LastPasswordChangedDate = c.LastPasswordChangedDate,
        CreationDate = c.CreationDate,
        Iscinstance = c.LinkUsersToIscinstances
            .SelectMany(l => l.Iscinstances)
            .Select(i =>
                new IscinstanceModel {
                    IscinstanceId = l.IscinstanceId,
                    Name = l.name
                }
            ),
        UserProfile = new [] {
            new UserProfileModel{
                ProfileName = c.Profile.ProfileName,
                Address1 = c.Profile.Address1,
                DirectConnectPhone = c.Profile.DirectConnectPhone,
                ProfilEmail = c.Profile.ProfilEmail
            }
        }
    })
    .ToListAsync();
  • Related