How do I map class object with Dapper - c#

I am currently mapping the database query output to a class object in the following. Is there anyway I can directly map it with out using foreach loop?
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Address { get; set; }
}
string select = "SELECT Id, Name, Address FROM emp where Id = 100";
string dbConnection="Server = TestServer; userid = XXXX; password = YYYYY; database = TestDB; port = 1234";
Person person = new Person();
using (var connection = new MySqlConnection(dbConnection))
{
var v = await connection.QueryAsync<Person>(select);
if (v != null)
{
foreach (var res in v)
{
person.Id = res.Id;
person.Name = res.Name;
person.Address = res.Address;
}
}
}

The code doesn't make logical sense as you are looping over a list of people & overwriting a single Person object with every new person being enumerated.
That aside, the result of await connection.QueryAsync<Person>(select); will be of type IEnumerable<Person>.
var v = await connection.QueryAsync<Person>(select);
is equal to:
IEnumerable<Person> = await connection.QueryAsync<Person>(select);
You already have a collection of Person objects mapped.

Related

How to do Linq query update

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";
}

Linq At least one object must implement IComparable

I am trying to order a List of Entities that contains another list of Entities. I have implemented IComparable for all entities and still get the exception. All of the examples I have seen address the issue where you have one list and you order by a given field in that list but not where you have a list of lists. This issue is happening for Linq to Objects per below and also for Linq to Entities. What am I missing?
[TestClass]
public class OrderBy
{
[TestMethod]
public void OrderByTest()
{
var hobbies = new Collection<Hobby> { new Hobby { HobbyId = 1, Name = "Eating" }, new Hobby() { HobbyId = 2, Name = "Breathing" } };
var p1 = new Person
{
PersonId = 1,
Name = "A",
PersonHobbies = new Collection<PersonHobby> { new PersonHobby() { PersonHobbyId = 1}}
};
var p2 = new Person
{
PersonId = 2,
Name = "Z",
PersonHobbies = new Collection<PersonHobby> { new PersonHobby() { PersonHobbyId = 2 }}
};
var people = new List<Person> { p1, p2 };
var pplEnumerable = people.AsEnumerable();
pplEnumerable = pplEnumerable.OrderByDescending(r => r.PersonHobbies.OrderByDescending(p => p.Hobby.Name));
foreach (var person in pplEnumerable)
{
Console.WriteLine(person.Name);
}
}
public class Person : IComparable
{
public int PersonId { get; set; }
public string Name { get; set; }
public virtual ICollection<PersonHobby> PersonHobbies { get; set; }
public int CompareTo(object obj)
{
if (obj == null) return 1;
var otherPerson = obj as Person;
return PersonId.CompareTo(otherPerson.PersonId);
}
}
public class PersonHobby : IComparable
{
public int PersonHobbyId { get; set; }
public int HobbyId { get; set; }
public virtual Person Person{ get; set; }
public int PersonId { get; set; }
public virtual Hobby Hobby { get; set; }
public int CompareTo(object obj)
{
if (obj == null) return 1;
var otherPersonHobby = obj as PersonHobby;
return PersonHobbyId.CompareTo(otherPersonHobby.PersonHobbyId);
}
}
public class Hobby : IComparable
{
public int HobbyId { get; set; }
public string Name { get; set; }
public int CompareTo(object obj)
{
if (obj == null) return 1;
var otherHobby = obj as Hobby;
return HobbyId.CompareTo(otherHobby.HobbyId);
}
}
}
You cannot apply ordering to lists by default. You need to write up a custom class (sort of EquatableList etc.) or use LINQ Except & Intersect operators to compare lists.
But based on your comment, if you're looking for the LINQ equivalent of:
select * from Person p join PersonHobby ph
on ph.PersonId = p.PersonId join Hobby h
on h.HobbyId = ph.HobbyId order by h.Name
then that can be achieved as:
var query = people.SelectMany(p => p.PersonHobbies)
.Join(hobbies, ph => ph.HobbyId, h => h.HobbyId,
(ph, h) => new
{
Person = ph.Person, PersonHobby = ph, Hobby = h
})
.OrderBy(r => r.Hobby.Name);
basically we join person, person hobbies and hobby on the keys, and project all columns and sort it by the hobby.name field, as mentioned in your SQL.

Query on two inherited classes in EF Code First

I'm using EF code first and I have two classes that inherited from a base class(TPT):
public class Party
{
public int PartyId {get; set;}
}
public Person:Party
{
string FirstName { get; set; }
string LastName { get; set; }
}
public Organization:Party
{
string Name { get; set; }
}
Now, I want to create a query to fetch all Persons that their LastNames are equal to "SomeName" and all Organizations that their Name begins with "A" in one transaction.
Something like this
IList<Party> GetParties(string name, string organizationName)
{
IList<Party> result = new List<Party>();
using(var context = new MyContext())
{
var persons = context.Parties.OfType<Person>().Where(t=>t.LastName = name) ;
var organizations = context.Parties.OfType<Organization>().Where(t=>t.Name.StartWith(organizationName));
//return merge of persons and organizations
}
}
Is there any way to do this?
You can do
context.Parties.OfType<Person>().Where(t=>t.LastName = name).OfType<Party>()
.Concat(context.Parties.OfType<Organization>()
.Where(t=>t.Name.StartWith(organizationName)))
You don't have to cast the second collection to Party because it is concatenated with an IQueryable<Party> which is covariant with IQueryable<Organization>.
I did some LINQPad fiddling and I believe that this is the result you want.
IList<Party> GetParties(string name, string organizationName)
{
IList<Party> result = new List<Party>();
using(var context = new MyContext())
{
var persons = context.Parties.OfType<Person>().Where(t=>t.LastName = name) ;
var organizations = context.Parties.OfType<Organization>().Where(t=>t.Name.StartWith(organizationName));
//return merge of persons and organizations
result = (IList<Party>)persons.Union((IEnumerable<Party>)organizations);
}
return result;
}

AutoMapper Map object to array

I have an entity called ActionResult that my methods along the application returns. Now i want to map a returned object in the ActionResult to it's right place in an array of that object...
public class Core
{
public Employee[] Employees = new[] {
new Employee {
Name = "Jack",
Age = 21,
Salary = 1000
},
new Employee {
Name = "Carl",
Age = 35,
Salary = 1000
},
new Employee {
Name = "Tom",
Age = 41,
Salary = 1000
},
};
}
public class ActionResult
{
public string ActionID { get; set; }
public Employee Employee { get; set; }
}
public class Employee
{
public String Name { get; set; }
public int? Age { get; set; }
public int? Salary { get; set; }
public int? Level { get; set; }
}
public ActionResult MethodThatReturnsActionResultWithAnEmployee()
{
return new ActionResult {
ActionID = new Guid().ToString(),
Employee = new Employee {
Name = "Carl",
Age = 35,
Salary = 7000,
Level = 1
}
};
}
Now as you can see what i want to do is taking the Employee that is returned from the Method, and search in the array of Employees in the Core and update it using the new given data using AutoMapper.
AutoMapper will not search employee in some array for you. How it would know which employees should be considered as equal? You should search for employee manually, and use appropriate mapping method to update existing instance of employee with data from other employee instance:
Mapper.CreateMap<Employee, Employee>();
var result = MethodThatReturnsActionResultWithAnEmployee();
var employee = result.Employee;
var core = new Core();
var employeeToUpdate =
core.Employees.FirstOrDefault(e => e.Name == employee.Name);
Mapper.Map(employee, employeeToUpdate);
If you really want mapping to look like
Mapper.Map(result, core);
Then you should write your own type mapper for this:
public class ActionResultToCoreConverter : ITypeConverter<ActionResult, Core>
{
public Core Convert(ResolutionContext context)
{
var result = (ActionResult)context.SourceValue;
var employee = result.Employee;
var core = (Core)context.DestinationValue ?? new Core();
var employeeToUpdate =
core.Employees.FirstOrDefault(e => e.Name == employee.Name);
Mapper.Map(employee, employeeToUpdate);
return core;
}
}
And mapping will look like:
Mapper.CreateMap<Employee, Employee>(); // this map also required
Mapper.CreateMap<ActionResult, Core>()
.ConvertUsing<ActionResultToCoreConverter>();
var result = MethodThatReturnsActionResultWithAnEmployee();
var core = new Core();
Mapper.Map(result, core);
// if you want to create new Core instanse:
var core2 = Mapper<Core>(result);

Accessing a variable using a string containing the variable's name [duplicate]

This question already has answers here:
string to variable name
(4 answers)
Closed 9 years ago.
I am reading the name of a string variable from the database (e.g. "_datafile"). I want to know how I can access a named variable within my program using this string.
I have already tried using a dictionary, hash table, and a switch-case statement but I would like to have the variable resolve itself dynamically. Is this possible?
Do you mean you want to get the value of a field using the field name as a string?
public class MyClass
{
public string _datafile;
public MyClass()
{
_datafile = "Hello";
}
public void PrintField()
{
var result = this.GetType().GetField("_datafile").GetValue(this);
Console.WriteLine(result); // will print Hello
}
}
EDIT: #Rick, to respond to your comment:
public class MyClass
{
public IEnumerable<string> _parameters = new[] { "Val1", "Val2", "Val3" };
public void PrintField()
{
var parameters = this.GetType().GetField("_parameters").GetValue(this) as IEnumerable;
// Prints:
// Val1
// Val2
// Val3
foreach(var item in parameters)
{
Console.WriteLine(item);
}
}
}
If you want to get the value of a field based on its string name you will have to use reflection.
class MyClass
{
public int DataFile { get; set; }
public int _datafile;
}
var ob = new MyClass();
var typ = typeof(MyClass);
var f = typ.GetField("_datafile");
var prop = typ.GetProperty("DataFile");
var val = f.GetValue(ob);
var propVal = prop.GetValue(ob);
Usually you would create a class representing the values of one table record. If your table has an ID a FirstName and a LastName column, you would create a class like this
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Then you create a list of persons
var people = new List<Person>();
Now you can add persons to the list.
var p = new Person();
p.ID = 5;
p.FirstName = "John";
p.LastName = "Doe";
people.Add(p);
You can use a DataReader in order to read from a table
string sql = "SELECT * FROM tblPerson WHERE LastName LIKE #pattern";
cmd = new SqlCommand(sql);
cmd.Connection = "server=test;uid=sa;pwd=manager;database=northwind";
cmd.Parameters.AddWithValue("#pattern", "A%"); // Names beginning with "A"
using (SqlDataReader reader = cmd.ExecuteReader()) {
// Get column indexes
int idOrdinal = reader.GetOrdinal("ID");
int firstNameOrdinal = reader.GetOrdinal("FirstName");
int lastNameOrdinal = reader.GetOrdinal("LastName");
while(reader.Read()) {
var p = new Person();
p.ID = reader.GetInt32(idOrdinal);
p.FirstName = reader.GetString(firstNameOrdinal);
p.LastName = reader.GetString(lastNameOrdinal);
people.Add(p);
}
}

Categories

Resources