How to do Linq query update - c#

I have the following method to return the data of two entities.
public List<Object> GetDados()
{
var sendFilter = new Filter<MessageSent>();
//employeeFilter.Add(x => x.Name, name);
sendFilter.Add(x => x.MessageSentSeq, ID_GROUP_SEND);
// You can add more filters
MessageSentService svc = new MessageSentService();
var messages = svc.Find(sendFilter).ToList();
var employees = new EmployeeService().GetAll();
var query =
from employee in employees
join message in messages
on employee.EmployeeId equals message.EmployeeId
select new
{
MessageSentId = message.MessageSentId,
//EmployeeId = message.EmployeeId,
//MessageSentSeq = message.MessageSentSeq,
Name = employee.Name,
Surname = employee.Surname,
Mobile = employee.Mobile,
Email = employee.Email,
Status = "N"
};
return query.ToList<Object>();
}
Call
ILog log = LogManager.GetLogger(typeof(Form));
List<Object> Send;
Send = GetDados();
gvSent.DataSource = Send;
When doing send I would like to update the record that is inside object var query that in turn populates my grid
I need to set the status field with S at the end of everything I updated my database with the items that were sent correctly.

Because your function returns a List<Object>, you'll be unable to modify those properties without using Reflection or some other drastic measure. If you plan on this data being modifiable, you'll need to make sure the data you're returning is typed. First define a simple class:
class Dado
{
public string MessageSentId { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public bool Mobile { get; set; }
public string Email { get; set; }
public string Status { get; set; }
}
...then modify your function to return instances of this type:
public List<Dado> GetDados()
{
var sendFilter = new Filter<MessageSent>();
//employeeFilter.Add(x => x.Name, name);
sendFilter.Add(x => x.MessageSentSeq, ID_GROUP_SEND);
// You can add more filters
MessageSentService svc = new MessageSentService();
var messages = svc.Find(sendFilter).ToList();
var employees = new EmployeeService().GetAll();
return (
from employee in employees
join message in messages
on employee.EmployeeId equals message.EmployeeId
select new Dado
{
MessageSentId = message.MessageSentId,
//EmployeeId = message.EmployeeId,
//MessageSentSeq = message.MessageSentSeq,
Name = employee.Name,
Surname = employee.Surname,
Mobile = employee.Mobile,
Email = employee.Email,
Status = "N"
}
).ToList();
}
Now, in your code after populating the grid can do something like:
foreach (var dado in Send) {
dado.Status = "S";
}

Related

Map list manually from context

Initially I was using automapper for this but its seems way harder for me to implement it.
Basically, I just want to return an empty list instead of null values. I can do this on projects level but not on teammates level. The API must not return a null because the UI that consumes it will have an error.
Sample of my implementation below:
Projects = !Util.IsNullOrEmpty(x.Projects) ? x.Projects : new List<ProjectsDto>(),
Ill highly appreciate if someone can guide me on how to manually map this with null/empty checking.
If you can also provide and example using automapper that too will be very helpful.
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public List<ProjectsDto> Projects { get; set; }
}
public class ProjectsDto
{
public string Status { get; set; }
public List<TeammatesDto> Teammates { get; set; }
}
public class TeammatesDto
{
public string TeammateName { get; set; }
public string PreviousProject { get; set; }
}
//Get by Id
var employee = await _context.Employees
.Where(x => x.id.Equals(request.Id)
.FirstOrDefaultAsync(cancellationToken);
//Map employee
EmployeeDto ret = new EmployeeDto()
{
Id = employee.id,
Name = employee.Name,
Projects = null //TODO: map manually
}
//Get all employees
var employees = await _context.Employees.AsNoTracking()
.ToListAsync(cancellationToken);
//Map here
IList<EmployeeDto> list = new List<EmployeeDto>();
foreach (var x in employees)
{
EmployeeDto dto = new EmployeeDto()
{
Id = x.id,
Name = x.Name,
Projects = null //TODO: map manually
};
list.Add(dto);
}
return list;
Instead of materializing full entities, do the following:
var query = _context.Employees
.Select(e = new EmployeeDto
{
Id = e.id,
Name = e.Name,
Projects = e.Projects.Select(p => new ProjectDto
{
Status = p.Status,
Templates = p.Templates.Select(t => new TemplateDto
{
TeammateName = t.TeammateName,
PreviousProject = t.PreviousProject
}).ToList()
}).ToList()
}
);
var result = await query.ToListAsync();

Using Linq to read from multiple tables

I'm sure someone else has asked this but I searched on what I could think of to find the solution.
I've got the following data models to match tables in my SQL db:
public class ProfileDetailModel
{
public string id { get; set; }
public string name { get; set; }
public StyleList[] styleList { get; set; }
public FabricList[] fabricList { get; set; }
}
public class StyleList
{
public string id { get; set; }
public string name { get; set; }
}
public class FabricList
{
public string id { get; set; }
public string fabricName { get; set; }
}
This is the current query code:
var query = (from t in db.tblProfiles
select new ProfileDetailModel()
{
id = t.id,
name = t.name
});
var querylist = await query.ToListAsync();
(prototyped linq queries below for style and fabric)
var styleQuery = (from t in db.tblStyles
select new styleList()
{
id = t.id,
name = t.name
});
var fabricQuery = (from t in db.tblFabrics
select new fabricList()
{
id = t.id,
name = t.name
});
if (queryList.Count > 0)
{
var item = queryList[0];
item.styleList = styleQuery;
item.fabricList = fabricQuery;
}
I'll have one profileDetailModel with multiple items in styleList and in fabricList. EG.
ProfileDetailModel
Data: Pants
styleList: Bell Bottom, Straight Leg, Boot fit
fabricList: jean-blue, jean-black, plaid
All three above models are tables in my db. I could issue 3 separate queries to read the data then assemble after the fact. But is there a way I can do a linq query to include the two arrays in the main query in one shot?
Try this:
var newQuery = (from p in db.tblProfiles
select p)
.AsEnumerable()
.Select(x => new ProfileDetailModel()
{
id = x.id,
name = x.name,
styleList = styleQuery,
fabricList = fabricQuery
});

Merging 2 lists of different objects into a third list of a different type?

I'm building an API wrapper for a third party API that translates their objects into business domain objects that can be used for other processing. In this case, I need to take 2 different objects Contact and User and merge them into a single list of objects called UserContacts. I'm matching these objects based on their Email property, and if there is no matching elements, a new one is inserted.
Here are my current objects and methods, I'm just trying to figure out if there's a better/faster method.
public class ContactUser : IUser
{
public string SalesForceUserId { get; set; }
public string SalesForceContactId { get; set; }
public string ZendeskId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
private List<IUser> MergeContactsAndUsers()
{
var sfContacts = SalesForceCache.Contacts.Data;
var sfUsers = SalesForceCache.Users.Data;
var newUsers = sfUsers.Select(user => new ContactUser
{
SalesForceUserId = user.Id,
Name = user.Name,
FirstName = user.FirstName,
LastName = user.LastName,
Email = user.Email
}).Cast<IUser>().ToList();
foreach (var contact in sfContacts)
{
var tmp = newUsers.FirstOrDefault(n => n.Email == contact.Email);
if (tmp != null)
{
tmp.SalesForceContactId = contact.Id;
}
else
{
var newUser = new ContactUser
{
SalesForceContactId = contact.Id,
Name = contact.Name,
FirstName = contact.FirstName,
LastName = contact.LastName,
Email = contact.Email
};
newUsers.Add(newUser);
}
}
return newUsers;
}
If you want to replace your current implementation with Join you can have something like this:
private List<IUser> MergeContactsAndUsers()
{
var sfContacts = SalesForceCache.Contacts.Data;
var sfUsers = SalesForceCache.Users.Data;
var leftJoinResults =
sfUsers.Join(
sfContacts,
u => u.Email,
c => c.Email,
(u, c) => new ContactUser()
{
SalesForceContactId = c.SalesForceContactId,
SalesForceUserId = u.Id,
Name = u.Name,
FirstName = u.FirstName,
LastName = u.LastName,
Email = u.Email
}).Cast<IUser>().ToList();
var rightJoinResults =
sfContacts
.Where(c => !leftJoinResults.Select(nu => nu.SalesForceContactId).Contains(c.Id))
.Select(c => new ContactUser
{
SalesForceContactId = c.Id,
Name = c.Name,
FirstName = c.FirstName,
LastName = c.LastName,
Email = c.Email
});
leftJoinResults.AddRange(rightJoinResults);
return leftJoinResults;
}
But because Join is only a left join (and you need right join as well) it still requires an additional query to get missing contacts (the query to get rightJoinResults).
It's more of an alternative implementation with use of Join. Without proper measurements it's hard to tell whether it's faster.

Add a list of DTOs to the master DTO

I have two DTOs:
public class MasterDTO
{
public int Id { get; set; }
public string Name { get; set; }
public List<DetailDTO> Details { get; set; }
}
public class DetailDTO
{
public int Id { get; set; }
public string DetailName { get; set; }
}
Also, I have a function:
using (var context = new Context())
{
var r = context.MasterData
.Select(d => new MasterDTO
{
Id = d.Id,
Name = d.Name,
}
}
I need to fill the list of DetailDTOs too and do it in a single request.
At this moment, I have to get list of DetailsData data and add it through foreach to the MasterDTO, which, of course causes a lot of requests to the database server.
Is there a better solution?
In your data call, do an eager load on your DetailData.
Example:
var r = context.MasterData.Include("DetailData")
DetailData should be the name of your navigation property attached to your MasterData entity.
This will cause detail data to be pulled along with your call for MasterData.
The full call may look something like this:
using (var context = new Context())
{
context.LazyLoadingEnabled = false;
var r = context.MasterData.Include("DetailData")
.Select(d => new MasterDTO()
{
Id = d.Id,
Name = d.Name,
Details = d.Details.Select(dt => new DetailDTO()
{
Id = dt.Id,
DetailName = dt.DetailName
})
});
}

Linq to objects filtering IN and not in

Looking for an example where I can filter my collection based on some filtering criteria.
I have been looking for some example where given a list /array i can filter a collection.
In the example below in my find method I am trying to filter based on 2 values ,looking for something like an "IN" function any suggestions?
class Program
{
static void Main()
{
//Print all customres that belong to below deparments and match on surname
var criteria=new Criteria
{
Departments = new List<string> {"BusinessAnalyst", "Account"},
Surname = "Bloggs"
};
List<Customer> customers = Repository.Find(criteria);
customers.ForEach(x => Console.WriteLine(string.Format("Surname: {0} Department :{1}", x.Surname,x.Department)));
Console.Read();
}
}
public class Repository
{
public static List<Customer>GetCustomers()
{
return new List<Customer>
{
new Customer { Name = "Jon",Surname="Smith",Department = DepartmentType.Managers},
new Customer{Name = "Bill",Surname = "Gates",Department = DepartmentType.Managers},
new Customer { Name = "Mary",Surname = "Bug",Department = DepartmentType.Developers},
new Customer { Name = "Mark",Surname="Boo",Department = DepartmentType.Account},
new Customer{Name = "Ron",Surname = "Scott",Department = DepartmentType.Managers},
new Customer { Name = "Jonny",Surname = "Dip",Department = DepartmentType.Developers},
new Customer { Name = "Mary",Surname = "Bloggs",Department = DepartmentType.BusinessAnalyst},
new Customer { Name = "Mary",Surname = "Bug",Department = DepartmentType.Account},
new Customer { Name = "Jonny",Surname = "Dip",Department = DepartmentType.Account},
new Customer { Name = "Mary",Surname = "Bloggs",Department = DepartmentType.Managers}
};
}
public static List<Customer> Find(Criteria criteria)
{
List<Customer>customers=Repository.GetCustomers();
//Filter on departments
//ERROR HERE AS I cannot do this "IN" would be fantastic.
customers = customers.Contains(criteria.Departments);
//now filter on name
customers = customers.Where(x => x.Surname == criteria.Surname).ToList();
return customers;
}
}
public enum DepartmentType
{
Account,
Managers,
Developers,
BusinessAnalyst
}
public class Customer
{
public string Name { get; set; }
public string Surname { get; set; }
public DepartmentType Department { get; set; }
}
public class Criteria
{
public Criteria()
{
Departments=new List<string>();
}
public string Name { get; set; }
public string Surname { get; set; }
public List<string> Departments { get; set; }
}
public static List<Customer> Find(Criteria criteria)
{
List<Customer> customers = Repository.GetCustomers();
var customers2 = customers.Where(x => criteria.Departments.Contains(x.Department.ToString()));
var customers3 = customers2.Where(x => x.Surname == criteria.Surname);
return customers3.ToList();
}
But considering you use an enum for the Department (DepartmentType), shouldn't your Criteria class use the same instead of a string?
If you define the criteria.Departments as List<DepartmentType> then you can write
public static List<Customer> Find(Criteria criteria)
{
List<Customer> customers = Repository.GetCustomers();
var customers2 = customers.Where(x => criteria.Departments.Contains(x.Department));
var customers3 = customers2.Where(x => x.Surname == criteria.Surname);
return customers3.ToList();
}
Contains returns a bool defining whether a specified object is contained in a collection. Based on your example, you will need to use Where to filter the customers, then use Contains on the departments:
customers = customers.Where(c => criteria.Departments.Contains(c.Department));
i think you want something like this..
customers = customers.Where(c => criteria.Departments.Contains(c.Department));
You want
Customers.Where(c => criteria.Departments.Contains(c.Department.ToString()))
Not sure if this is what you're looking for but the following:
List<Customer> FilteredCustomers = (from c in customers where Criteria.Departments.Contains(c.deparment) && c.surname == Criteria.Surname select c).ToList();
Would equate to something like this in SQL:
SELECT *
FROM Customers
WHERE Department IN (
List of departments
)
AND Surname = surname
I haven't tested this but I think it should work and bring back what you want.

Categories

Resources