Using AutoMapper for JOIN operation without Foreign key - linq

I have db TABLES:
Company(CompanyId, Name, UserId, CompanyType, Uid)
User(UserId, FirstName, LastName, SocialNumber)
And in application MODEL:
CompanyModel(CompanyId, Name, CompanyType, Uid, UserName)
Since CompanyModel and Company have many same type and name Fields I tend to use AutoMapper to avoid writing explicitly all of those fields.
But here I now need to get UserName.
If UserId had FK I would have been able to do it like this:
var mapper = Mapper.CreateMap<Company,CompanyModel>();
mapper.ForMember(
d => d.UserName,
s => s.MapFrom(a => a.User.FirstName + " " + a.User.LastName));
var q = companyQuery.Project().To<CompanyModel>();
But UserId in Company table don't not have Foreign key relationship constrain with User and I can't create it.
So at the moment I am doing it with join:
var r =
from c in companyQuery
join u in userQuery on c.UserId equals u.UserId
select new CompanyModel
{
CompanyId = c.CompanyId,
Name = c.Name,
CompenyType = c.CompanyType,
Uid = c.Uid,
UserName = u.FirstName + " " + u.LastName
};
I would like to know if there is any way to do this with AutoMapper, and how? so I can skip naming all fields (this is just sample, there are much more fields).
Is anyone familiar with this ?

Related

get list from a class to fill taxtbox in other class by linq

how to get just special 2 attributes from a table to other table( and placement in related textbox) by LINQ??
public string srcht(ACTIVITIES sn)
{
db db = new db();
var q = (from i in db.costumers.Where(i => i.id== sn.id)select i.name).ToList();
return q.Single();
}
public string srcht(ACTIVITIES sn)
{
db db = new db();
var q = (from i in db.costumers.Where(i => i.id== sn.id)select i.family).ToList();
return q.Single();
}
i did linq twice to fill 2 textboxes by name and family in other table. can i do it by one LINQ?
So you have an Activity in sn, and you want the Name and the Family of all Customers that have an Id equal to sn.Id.
var result = db.Customers.Where(customer => customer.Id == sn.Id)
.Select(customer => new
{
Name = customer.Name,
Family = customer.Family,
});
In words: in the database, from the table of Customers, keep only those Customers that have a value for property Id that equals the value of sn.Id. From the remaining Customers select the values of Name and Family.
If you expect that there will only be at utmost one such customer (so if Id is the primary key), just add:
.FirstOrDefault();
If you think there will be several of these customers, add:
.ToList();
The result will be an object, or a list of objects of some anonymous type with two properties: Name and Family.
If you want to mix the Name and the Family in one sequence of strings, which I doubt, consider to put the Name and the Family in an array. Result is sequence of arrays of strings. To make it one array of Strings, use SelectMany:
var result = db.Customers
.Where(customer => customer.Id == sn.Id)
.Select(customer => new string[]
{
customer.Name,
customer.Family,
})
.SelectMany(customer => customer);

Sub query in linq to sql

I want to return the comma seperated of the sub query result in my sql command.
As follow:
Select [User].UserName,
(Select [Role].Name + ', '
From
Security.UserRole As UserRole
Inner Join
Security.[Role] As [Role]
On UserRole.RoleId = [Role].RoleId
Where UserRole.UserId = [User].UserId
For Xml Path('')
)
From Security.[User] As [User]
Basically each user has multiple roles, and I want to load the roles names in comma separated format for each user.
The result set in Sql is like :
Is there any way I can write this query in LINQ ?
Thanks
Try Code
Create a Method Get User roles Particular User
Public String GetuserRoles(int userid)
{
string strroles="";
(from UserRole in Security.UserRole
join Role in Security.Role on UserRole.RoleId equals Role.RoleId
where UserRole.UserId==userid
select new
{
strs = Role.Name + ","
}).ToList().ForEach(c => strroles = strroles + c.strs);
return strroles;
}
After Write Your Linq Query:
var result=( from p in Security.User select new {
UserName=p.UserName,
Roles=GetuserRoles(p.UserId)
}).ToList();

LINQ for 3 tables - new to LINQ

I have 3 tables
Users - UserID, Firstname, LastName, etc
Roles - RoleId, RoleName
Features - UserId, RoleId
I want to display Users with common features using LINQ
Please help
you can try a lookup:
//Associate the role names with the features
var featureRoles = dbContext.Roles.Join(dbContext.Features,
role => role.RoleId,
feature => feature.RoleId,
(role, feature) => new {
RoleId = feature.RoleId,
UserId = feature.UserId,
RoleName = role.RoleName
});
//Create ILookup
var lookup = dbContext.Users.Join(featureRoles,
user => user.UserID,
fr => fr.UserId,
(user, fr) => new {
User = user,
RoleName = fr.RoleName,
RoleId = fr.RoleId
})
.ToLookup(r => r.RoleName, s => s.User);
This will sort your users by their role name for example:
var users = lookup["role 1"];
foreach(var user in users)
{
Console.WriteLine("Users in Role 1:");
Console.WriteLine("\t{0} {1}", user.Firstname, user.Lastname);
}
Output:
"Users in Role 1:"
"John Smith"
"Foo Bar"
...
If you want to search by the role id in stead of the name then you will need to alter the lookup definition to .ToLookup(r=> r.RoleId, s=> s.User)
from u in Users
join f in Features on u.UserId equals f.UserId
join r in Roles on r.RoleId equals f.RoleId
where f.RoleId == 1
select new { u.FirstName,u.LastName,r.RoleName}

Automapper with linq how?

Ok, I'm really struggling with finding a good example of what I need to do. So, I'll ask here.
Let's say I have a entity class (EF) named Customer and a corresponding view-model class named CustomerViewModel.
Using AutoMapper, I have created the following mappings:
Mapper.CreateMap<CustomerViewModel, Customer>();
Mapper.CreateMap<Customer, CustomerViewModel>();
How would I modify the following code to make use of this mapping?
public static List<CustomerViewModel> GetCustomers()
{
using (var context = new GCSBaseEntities())
{
var query = from c in context.Customers
select new CustomerViewModel
{
CompanyName = c.CompanyName,
Id = c.Id,
EmailAddress = c.EmailAddress,
FirstName = c.FirstName,
LastName = c.LastName,
MiddleName = c.MiddleName,
ModifiedDate = c.ModifiedDate,
Phone = c.Phone,
SalesPerson = c.SalesPerson,
Suffix = c.Suffix,
Title = c.Title,
FullName = c.FirstName + " " + c.LastName
};
return query.ToList();
}
}
Thanks in advance.
When you register your mappings, you must provide any complex mapping operations that have to occur. In your case, I believe all your properties match up, except for FullName = c.FirstName + " " + c.LastName. Here's how your Customer-to-CustomerViewModel mapping should look:
Mapper.CreateMap<Customer, CustomerViewModel>()
.ForMember(custVm => custVm.FullName,
mapper => mapper.MapFrom(cust => cust.FirstName + " " + cust.LastName));
You'll have to figure out how to shove the FullName prop from the ViewModel back into the FirstName & LastName fields on the EF class, though. But when you decide how to implement it, follow the pattern from above for the other mapping.
Your query can now be MUUUCH smaller:
using (var context = new GCSBaseEntities())
{
return from c in context.Customers
select Mapper.Map<CustomerViewModel>(c);
}
Figured it out. In order to avoid the aforementioned error, you have to Add the call the .AsEnumerable() after Customers like so:
return from c in context.Customers.AsEnumerable()
select Mapper.Map<CustomerViewModel>(c);
I got this from this thread: LINQ and AutoMapper

How to Execute a method inside LINQ to Entities'

var users = from u in db.UserProfiles select new UsersViewModel{
UserName = u.UserName,
UserId = u.UserId,
IsDisabled = u.IsDisabled,
Role = Roles.GetRolesForUser(u.UserName).FirstOrDefault()
};
I would like to select the roles from the database and create a list of UsersViewModel. However Entity Framework is trying to execute the projection on the SQL side, where there is no equivalent to Roles.GetRolesForUser.
What would be an alternative to this or how am I suppose to execute any method inside the query?
The easiest is to get the data you want from SQL, then after the query executes, iterate through the results and populate the additional details from the function in your code.
Example:
var users = (from u in db.UserProfiles select new UsersViewModel{
UserName = u.UserName,
UserId = u.UserId,
IsDisabled = u.IsDisabled
}).ToList();
foreach(var user in users){
user.Role = Roles.GetRolesForUser(u.UserName).FirstOrDefault();
}
The key to remember here is to separate out what you're doing (understanding the separation of concerns in your architecture). Take care of the SQL first, then augment the data from other sources, in your case the Role Provider.
You can force the query to execute before creating the ViewModels by adding ToList():
var users = from u in db.UserProfiles.ToList()
select new UsersViewModel{
UserName = u.UserName,
UserId = u.UserId,
IsDisabled = u.IsDisabled,
Role = Roles.GetRolesForUser(u.UserName).FirstOrDefault()
};
As CodeMonkey1313 noted, I strongly suggest you apply some sort of filter in your query:
var users = from u in db.UserProfiles
.Where( x => /* apply filter here */ )
.ToList() //Force query to execute
select new UsersViewModel {
UserName = u.UserName,
UserId = u.UserId,
IsDisabled = u.IsDisabled,
Role = Roles.GetRolesForUser(u.UserName).FirstOrDefault()
};
You can convert your Queryable to an Enumerable that executes locally:
var users = (from u in db.UserProfiles select new UsersViewModel{
UserName = u.UserName,
UserId = u.UserId,
IsDisabled = u.IsDisabled)}
).AsEnumerable()
.Select(u => new {
UserName = u.UserName,
UserId = u.UserId,
IsDisabled = u.IsDisabled,
Role = Roles.GetRolesForUser(u.UserName) })
.FirstOrDefault()

Resources