Adding data to an existing model with real data to MVC - c#

I have a previous question that shows how my models look and it was adding FAKE data. Add to Existing Model based on a POCO with need to add to List<T>
Now I am wanting to add REAL data and i'm wondering how to do this. Should or need I loop over the result ??
public IActionResult FindPerson (FindPersonViewModel findPersonViewModel)
{
var firstName = findPersonViewModel.FirstName;
var middleName = findPersonViewModel.MiddleName;
var lastName = findPersonViewModel.LastName;
var emailAddress = findPersonViewModel.EmailAddress;
var genderTypeId = findPersonViewModel.GenderTypeId;
// GET REAL DATA
using (AzEdsIdentityContext context = new AzEdsIdentityContext(AzEdsIdentityContext.Options))
{
var result = context.FindPerson(firstName, lastName, genderTypeId);
// for loop on the result to hydrate new List<FindPersonResultsViewModel>() ?
}
// Note: here is exactly how I hydrated the model with fake data
findPersonViewModel.findPersonResultsViewModel = new List<FindPersonResultsViewModel>()
{ new FindPersonResultsViewModel { AZEDID = 33423432, PersonID = 3534454, FirstName = "John", LastName = "Williamson", MiddleName = "K", ExistInContactManager = false, ActionType = true, ContactType = "Principal", DOB = "5/1/1985", PhysicalAddress = "123 main st. mesa, az.", PreferredEmail = "john#aol.com", PreferredPhone = "602-393-4443"},
new FindPersonResultsViewModel { AZEDID = 33423432, PersonID = 3534454, FirstName = "Jon", LastName = "Williamson", MiddleName = "K", ExistInContactManager = false, ActionType = true, ContactType = "Principal", DOB = "5/1/1985", PhysicalAddress = "123 main st. mesa, az.", PreferredEmail = "john#aol.com", PreferredPhone = "602-393-4443"},
};
}

Given the Person model
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
And you obtain the result from your context
List<Person> result = context.getPersons();
You need a collection of a different but similar type, so you use a projection
List<PersonViewModel> result =
context.getPersons()
.Select(p => new FindPersonResultsViewModel
{
Name = p.Name,
Email = p.Email
}).ToList();
Then assign the collection property to another model
var model = new ResultViewModel
{
...
findPersonResultsViewModel = result
};
If you're getting back IEnumerable, do .ToList() to get the List<T>.

Related

Testing crud operations in SQLite, using the repository pattern

I m testing an app that my teacher made. I added the driver class, so every order has a driver associated with it, and a put the Driver as a foreign key in my Order class (So I have one to one relationship)
public class Order {
[ForeignKey("Driver")]
public int DriverId { get; set; }
public int Id { get; set; }
public List<Item> Items { get; set; }
}
public class Driver {
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[Range(1, 5)]
public int Rating { get; set; }
}
Then I went ahead and created the add, update and delete driver, and did the migration and update to the database.
Now I am tryin to test all this functionality, so I made some unit-test but the only ones that are passing are Add_customner and Add_drver everything else fails
So I am hoping to see if anyone can share some light
This are my test
[Test]
public void AddCustomer_ValidCustomer_ReturnsTrue() {
// Arrange
Customer customer = new Customer() {
Id = 1,
FirstName = "James",
LastName = "Cameron",
StreetAddress = "123 Sesame Street",
City = "New York City",
ZIP = "11111",
State = "NY",
PhoneNumber = "1111111111",
Email = "jc#terminator.com"
};
// Act
var result = uow.AddCustomer(customer);
// Assert
Assert.IsTrue(result);
var qCust = _context.Customers.Where(q => q.Id == 1).FirstOrDefault();
Assert.AreSame(qCust, customer);
}
[Test]
public void AddDriver_ValidDriver_ReturnsTrue() {
// Arrange
Driver driver = new Driver() {
ID = 1,
FirstName = "James",
LastName = "Cameron",
Rating = 4
};
// Act
var result = uow.AddDriver(driver);
// Assert
Assert.IsTrue(result);
var qDrive = _context.Drivers.Where(q => q.ID == 1).FirstOrDefault();
Assert.AreSame(qDrive, driver);
}
[Test]
public void RemoveDriver_ValidDriver_ReturnsTrue() {
// Arrange
Driver driver = new Driver() {
ID = 1,
FirstName = "James",
LastName = "Cameron",
Rating = 4
};
// Act
var result = uow.RemoveDriver(driver);
// Assert
var Drivera = _context.Drivers;
Assert.IsTrue(result);
var qDrive = _context.Drivers.Remove(driver);
Assert.AreNotEqual(Drivera, qDrive);
}
[Test]
public void UpdateDriver_ValidDriver_ReturnsTrue() {
Driver driver = new Driver() {
ID = 1,
FirstName = "James",
LastName = "Cameron",
Rating = 4
};
var result = uow.UpdateDriver(driver);
var qDrive = _context.Drivers.Where(q => q.ID == 1).FirstOrDefault();
Assert.AreSame(qDrive, driver);
}
}
}
For it to work it must return true
Make sure your UOW using the same object as _context? Make sure when setting up mocks your database context it is injected and assigned same object to UOW and _context. This might be the reason your read-only operations are passing but others are failing.
Since you name it _context, I assume it is an instance variable of your test class. So whenever a test run, a new test object create and thus _context. To test your operations other than add, you should assume the _context is empty. That means you should first add the driver and then test removing it.

Using Dictionary Parameters as Optional Arguments when Calling Method

I'm presently trying to use a dictionary values to name optional parameters when invoking a method. I'm not sure this is possible with c# but I do something similar with queries using dynamic SQL.
string[] dobArrayKey = {"dob: "};
string[] dobArrayValue = {txtDob.Text};
string[] ptntNumArrayKey = { "PatientID: " };
string[] ptntNumArrayValue = { txtOfficeMR.Text};
string[] nameArrayKey = { "FirstName: ", "LastName: " };
string[] nameArrayValue = { txtFirstname.Text, txtLastname.Text };
List<List<string>> searchResults = new List<List<string>>();
Dictionary<string[], string[]> searchCriteria = new Dictionary<string[], string[]>
{
{dobArrayKey,dobArrayValue}
,{ptntNumArrayKey,ptntNumArrayValue}
,{nameArrayKey,nameArrayValue}
};
foreach (var item in searchCriteria)
{
if (item.Value[0] != "" && item.Value[0] != null)
{
searchResults.Add(new List<string>());
for (int x = 0; x <= item.Key.Count(); x++)
{
string strJSON = doPatientSearch(Convert.ToInt32(au.UserID)
, Convert.ToInt32(Session["PracticeID"]), au.SessionID, item.Key[x].ToString() : item.Value[x].ToString() );
PatientSearchResponse ptLi = JsonConvert.DeserializeObject<PatientSearchResponse>(json2);
foreach (PatientList3 patient in ptLi.PatientList)
{
searchResults[x].Add(patient.PatientNumber);
}
}
}
}
public static string doPatientSearch(int UserID, int PracticeID, string SessionID, string PatientID = null,
,string first = null, string last = null, string dob = null, string social = null)
{
//search
}
My colleague suggested I change the method itself by removing all of the optional parameters and instead passing through a dictionary that contains all of the parameters and handling them inside the method.
I think that would work, but for curiosities sake I wanted to get some feedback and find out whether or not something like I'm attempting to do in the above code is possible.
If it is impossible but there is another way of achieving the desired outcome I'd love to see your suggestions.
Thank you in advance.
Pass an expression
Since the criteria are used post-hoc (i.e. by filtering a complete resultset), you can use LINQ to filter the results. For maximum flexibility, the caller can pass in an Expression to be used as a callback on each item to determine if it should be included.
To get a filtered resultset:
public IEnumerable<Patient> FindPatients(Func<Patient,bool> criteria)
{
return sourceData
.Where (criteria);
}
To return a single result:
public Patient FindPatient(Func<Patient,bool> criteria)
{
return sourceData
.Single(criteria);
}
The criteria expression is just a function that accepts a patient and returns a Boolean. The caller can write this any way desired, or insert it as a lambda expression.
var results = patients.FindPatients( p => p.LastName == "Doe" );
Or
var results = patients.FindPatients
(
p =>
p.LastName.Contains("Doe") &&
p.PracticeID == 12
);
Or
var singleResult = patients.FindPatient( p => p.UserID == 1);
As you can see, the caller can provide literally any criteria desired, and has the benefit of type safety and early binding. This is far superior to using a Dictionary which has neither.
Full example code:
class Patient
{
public int UserID { get; set; }
public int PracticeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DOB { get; set; }
public string Social { get; set; }
public override string ToString()
{
return string.Format("{0} {1} {2}", UserID, FirstName, LastName);
}
}
class PatientRepository
{
static private readonly List<Patient> sourceData = new List<Patient>
{
new Patient
{
UserID = 1, PracticeID = 10, FirstName = "John", LastName = "Doe", DOB = DateTime.Parse("1/2/1968"), Social="123456789"
},
new Patient
{
UserID = 2, PracticeID = 10, FirstName = "Jane", LastName = "Doe", DOB = DateTime.Parse("1/2/1958"), Social="123456790"
},
new Patient
{
UserID = 3, PracticeID = 10, FirstName = "John", LastName = "Carson", DOB = DateTime.Parse("4/1/1938"), Social="123456791"
}
};
public IEnumerable<Patient> FindPatients(Func<Patient,bool> criteria)
{
return sourceData
.Where (criteria);
}
public Patient FindPatient(Func<Patient,bool> criteria)
{
return sourceData
.Single(criteria);
}
}
public class Program
{
public static void Main()
{
//Get a reference to the data store
var patients = new PatientRepository();
Console.WriteLine("Multiple record search");
var results = patients.FindPatients
(
p => p.LastName == "Doe"
);
foreach (var p in results)
{
Console.WriteLine(p);
}
Console.WriteLine("Single record search");
var singleResult = patients.FindPatient
(
p => p.UserID == 1
);
Console.WriteLine(singleResult);
}
}
Output:
Multiple record search
1 John Doe
2 Jane Doe
Single record search
1 John Doe
See the working code on DotNetFiddle

How to copy all fields from one object to another, but only when destination value is NULL

I'd like to merge one object into another in a generic way that can be used repeatedly for other more complex objects. I only want the NULLs to change.
ie. merge sourcePerson and detinationPerson to get resultingPerson (below)
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int? Age { get; set; }
public string Address { get; set; }
}
var sourcePerson = new Person
{
FirstName = "Bill",
LastName = "Smith",
Age = 43,
Address = "123 Some Street"
};
var destinationPerson = new Person
{
FirstName = "Barbara",
LastName = null,
Age = 41,
Address = null
};
var resultingPerson = new Person
{
FirstName = "Barbara",
LastName = "Smith",
Age = 41,
Address = "123 Some Street"
};
I've tried Automapper, but can't seem to configure it properly. I feel like the following should work. Help?
Mapper.CreateMap<Person, Person>().ForAllMembers(opt => opt.UseDestinationValue());
Mapper.Map(sourcePerson, destinationPerson);
Thanks IronGeek and tutok.
Yes, the following works:
Mapper.CreateMap<Person, Person>()
.ForAllMembers(opt => opt.Condition(person => person.DestinationValue == null));
Your can use reflection like this:
public static T Merge<T>(T source, T destination)
{
var returnvalue = (T) Activator.CreateInstance(typeof (T));
foreach (var field in destination.GetType().GetProperties())
{
field.SetValue(returnvalue,
field.GetValue(destination, null) == null ? field.GetValue(source) : field.GetValue(destination));
}
return returnvalue;
}
I haven't tested this for other than simple DTOs.

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);

Need help on developing LINQ Lambda expresssion to filter on a Schedule

I am having a hard time finding the lambda expression to call on a list to correctly filter an object structure. I was hoping someone here could help out. I am using .NET 3.5, and LINQ and the object domain is set up from Linq to SQL DBML. I specifically want to use lambda expressions.
The object structure is one where persons have settings, and one setting is a Schedule name, which corresponds to another schedule class with a StartDate and End Date.
public class MyPerson
{
public int ID { get; set; }
public List<MySetting> Settings { get; set; }
}
public class MySetting
{
public int ID { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
public class MySchedule
{
public string ID { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
Schedules have Start and End Dates, and a person's State can be Active or Scheduled.
List<MySchedule> schedules = new List<MySchedule>();
MySchedule scheduleA = new MySchedule { ID = "ScheduleA", StartDate = Convert.ToDateTime("1/1/2008"), EndDate = Convert.ToDateTime("12/31/2008") };
MySchedule scheduleB = new MySchedule { ID = "ScheduleB", StartDate = Convert.ToDateTime("1/1/2009"), EndDate = Convert.ToDateTime("12/31/2009") };
schedules.Add(scheduleA);
schedules.Add(scheduleB);
List<MySetting> settingsJill = new List<MySetting>();
MySetting settingFirstName = new MySetting { ID = 1, Name = "FirstName", Value = "Jill" };
MySetting settingScheduleName = new MySetting { ID = 2, Name = "ScheduleName", Value = "ScheduleB" };
MySetting settingState = new MySetting { ID = 3, Name = "State", Value = "Scheduled" }; // Jill uses ScheduleB
settingsJill.Add(settingFirstName);
settingsJill.Add(settingScheduleName);
settingsJill.Add(settingState);
List<MySetting> settingsBill = new List<MySetting>();
settingFirstName = new MySetting { ID = 1, Name = "FirstName", Value = "Bill" };
settingScheduleName = new MySetting { ID = 2, Name = "ScheduleName", Value = "ScheduleA" };
settingState = new MySetting { ID = 3, Name = "State", Value = "Scheduled" }; // Bill is Scheduled last year
settingsBill.Add(settingFirstName);
settingsBill.Add(settingScheduleName);
settingsBill.Add(settingState);
List<MySetting> settingsJane = new List<MySetting>();
settingFirstName = new MySetting { ID = 1, Name = "FirstName", Value = "Jane" };
settingScheduleName = new MySetting { ID = 2, Name = "ScheduleName", Value = "ScheduleA" };
settingState = new MySetting { ID = 3, Name = "State", Value = "Active" }; // Jane is Active
settingsJane.Add(settingFirstName);
settingsJane.Add(settingScheduleName);
settingsJane.Add(settingState);
List<MyPerson> persons = new List<MyPerson>();
MyPerson Jane = new MyPerson { ID = 1, Settings = settingsJane };
MyPerson Jill = new MyPerson { ID = 2, Settings = settingsJill };
persons.Add(Jane);
persons.Add(Jill);
persons.Add(Bill);
I want to filter the persons List by creating a lambda expression that will return persons with State = "Active" OR with a ScheduleName containing a current Date between the Start and End Date. In other words, Jill should appear in the filtered list since she is Scheduled, and she uses ScheduleB, and ScheduleB is for 2009, and today is 6/17/2009.
I am starting with
List<MyPerson> filter = persons.Select ( // and this is where I get stuck.
Thanks in advance for any help.
You need to rethink how you are storing the information. .NET Collectionns aren't SQL tables, and you shouldn't use them like so. That being said, here's the query you wanted:
Persons.Where(person =>
person.Settings.Any(setting=>
(setting.Name == "State" && setting.Value=="Active")) ||
person.Settings
.Where(setting=> setting.Name == "ScheduleName")
.Any(setting => { var sch = schedules
.First(schedule=>schedule.ID == setting.Value);
return sch.StartDate < DateTime.Now && sch.EndDate > DateTime.Now;
})
)
Imagine if you had a data structure like:
class Person {
Dictionary<string, string> Settings;
List<MySchedule> Schedules;
}
then your query would be
Persons.Where(person =>
Person.Settings["State"] == "Active" ||
Person.Schedules.Any(schedule =>
Datetime.Now > schedule.StartTime &&
DateTime.Now < schedule.EndTime
)
)
One problem is that you're starting with a Select. That's for projection - you're just trying to filter, so you only need Where.
Another problem is that your MyPerson type doesn't include a ScheduleName or State property. It's really not clear how it's all meant to hang together. If you could correct your example, I'm sure we can come up with the filter.

Categories

Resources