SubSonic 3 - Simple repository - One to many relations - subsonic

It's the first time I use Subsonic.
Let say I have those classes :
public class Store
{
public int Id { get; set; }
public String Name { get; set; }
}
public class Employee
{
public int Id { get; set; }
public String Name { get; set; }
}
An employee is related to a store with is hired date. This means that in the database I will have a middle table With StoreId, EmployeeId, StartDate, EndDate
UPDATE
An employee can work to the StoreA from 2009-01-01 to 2009-04-04 and work for StoreB from 2009-04-05 to ... And I don't want that my data table repeat all the information of my employee each time an employee change the store he working for. In this example employee have only a name, but lets say an employee got 10 property (adress, age, gender ...)
How could I achieve that ?

Based on your comment and the updated question it looks like you want something like the following:
public class Store
{
public int Id { get; set; }
public String Name { get; set; }
}
public class StoreEmployee
{
public int Id { get; set; }
public Employee Employee { get; set; }
public Store Store { get; set; }
public DateTime HiredDate { get; set; }
}
public class Employee
{
public int Id { get; set; }
public String Name { get; set; }
}

You'll actually need a many-to-many relationship which will join an Employee record to a Store Record, with a payload of Start and End Dates.
The Objects will look like this:
public class Store
{
public int Id { get; set; }
public String Name { get; set; }
}
public class Employee
{
public int Id { get; set; }
public String Name { get; set; }
public IList<EmploymentTerm> EmploymentTerms { get; set; }
}
public class EmploymentTerm
{
public int Id { get; set; }
public Store Store { get; set; }
public Employee Employee { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
Did this freehand so there could be a couple errors.

Related

How to use AutoMapper to create mapping from single class to nested class

My class structure looks like this. What I'm trying to do is, create automap from source EmployeeInfo class to destination NewEmployeeInfo class and vise Versa.
public class EmployeeInfo ///// Old Employee class - Transform this into New
{
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
public int DepartmentID { get; set; }
public string DepartmentName { get; set; }
}
public class NewEmployeeInfo //// New Employee -- Transform in to this
{
public Employee Employee { get; set; }
public Department Department { get; set; }
}
public class Employee
{
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
}
public class Department
{
public int DepartmentID { get; set; }
public string DepartmentName { get; set; }
}

Domain Driven Design Model

I am building ParkingReservation in DDD, In short means that people can invite place and when the car get in the camera identify the model and update the status of the place.
I divided the model to three Bounded contexts:
The first is Reservation Context that include the following objects:
`public class Lot
{
public int ID { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
public List<Place> Places { get; set; }
}
public class Place
{
public int ID { get; set; }
public int FloorNumber { get; set; }
public int RowNumber { get; set; }
public int ParkingNumber { get; set; }
}
public class Car
{
public int ID { get; set; }
public string Model { get; set; }
}
public class Driver
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public int Age { get; set; }
public Gender Gender { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public bool AcceptAdsToMail { get; set; }
public byte[] PictureData { get; set; }
public DateTime RegistrationTime { get; set; }
public DriverStatuses DriverStatuses { get; set; }
}
public class Reservation
{
public int ID { get; set; }
public Driver Driver { get; set; }
public Car Car { get; set; }
public Place Place { get; set; }
public DateTime OrderTime { get; set; }
public DateTime ParkingStartTime { get; set; }
public DateTime ParkingEndTime { get; set; }
public ParkingStatuses ParkingStatus { get; set; }
}
public class ParkingHistory
{
public int ID { get; set; }
public Place Place { get; set; }
public Driver Driver { get; set; }
public Car Car { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
}`
The Parking Lot has list of places
the Driver reserve place through the application
the saved place saved in the Reservation object and when the parking time
elapsed, new parkinghistory added to parkinghistories list that belong to driver and car so you can watch history per car or driver.
for this context of Reservation:
(1) Is it correct to put Driver and Reservation for the Aggregate Roots? or maybe Lot too?
(2) Place is entity or value object?
Thank you
The main goal of your use case is scheduling. You need to think about a consistency boundary around that idea. To avoid time slots overlapping for a place in a lot you will need to create a new abstraction for the purpose.
"PlaceInLotReservations" sounds as a good option as an value object to serve as a factory for a Reservation aggregate. In order to represent reality of how scheduling works you should feed that aggregate in the context of a day, so "PlaceInLotReservationsRepository" should has a "findByDate" method that collects all Reservations for a place in a given datetime.
So the semantics would be something like:
val placeInLotReservations = PlaceInLotReservationsRepository.findBy(datetime)
val reservation = placeInLotReservations.reserveFor(car, driver, startingTime, endingTime)
ReservationsRepository.save(reservation)
If there are lot of reservations in a place and so race conditions you can even make the VO smaller by passing in day quarters instead of a day for the initial look up.
BTW, can and driver are VOs in the context of the Reservation aggregate (they are not aggregates).
You can also have the history by querying the Reservation repository, you donĀ“t need ParkingHistory.
Hope it helps.

ServiceStack AutoQuery - Anomaly When Using "?Fields="

We have noticed an anomaly when using "?Fields=" in version 4.0.55 (pre-release on MyGet).
We have an Employee table with three 1:1 relationships - EmployeeType, Department and Title:
public partial class Employee {
[PrimaryKey]
[AutoIncrement]
public int ID { get; set; }
[References(typeof(EmployeeType))]
public int EmployeeTypeID { get; set; }
[References(typeof(Department))]
public int DepartmentID { get; set; }
[References(typeof(Title))]
public int TitleID { get; set; }
.
.
.
}
public class EmployeeType {
[PrimaryKey]
public int ID { get; set; }
public string Name { get; set; }
}
public class Department {
[PrimaryKey]
public int ID { get; set; }
public string Name { get; set; }
[Reference]
public List<Title> Titles { get; set; }
}
public class Title {
[PrimaryKey]
public int ID { get; set; }
[References(typeof(Department))]
public int DepartmentID { get; set; }
public string Name { get; set; }
}
The latest update to 4.0.55 allows related DTOs to be requested using ?Fields= on the query string like this:
/employees?fields=id,firstname,lastname,departmentid,department
Note that the "proper" way to request a related DTO (department) is to also request the foreign key field (departmentid, in this case).
We wondered if there was a way to return all of the Employee table fields and only selected related DTOs, so in testing we found that this request works:
/employees?fields=department
We get back all the Employee table fields plus the related Department DTO - with one strange thing - the Employee's ID field is populated with the Employee's TitleID values.
Specifying the foreign key field in the request fixes that anomaly:
/employees?fields=id,departmentid,department
but we lose all of the other Employee fields.
Is there a way that to get all of the Employee fields and selected related DTOs?
Here is our AutoQuery DTO:
[Route("/employees", "GET")]
public class FindEmployeesRequest : QueryDb<Employee>,
IJoin<Employee, EmployeeType>,
IJoin<Employee, Department>,
IJoin<Employee, Title> {
public int? ID { get; set; }
public int[] IDs { get; set; }
public string UserID { get; set; }
public string[] UserIDs { get; set; }
public int? EmployeeTypeID { get; set; }
public int[] EmployeeTypeIDs { get; set; }
public int? DepartmentID { get; set; }
public int[] DepartmentIDs { get; set; }
public int? TitleID { get; set; }
public int[] TitleIDs { get; set; }
public string LastNameStartsWith { get; set; }
public DateTime[] DateOfBirthBetween { get; set; }
public DateTime[] HireDateBetween { get; set; }
public bool? IsActive { get; set; }
[QueryDbField(Template = "(MONTH({Field}) = {Value})", Field = "DateOfBirth")]
public int? BirthMonth { get; set; }
[QueryDbField(Template = "(DAY({Field}) = {Value})", Field = "DateOfBirth")]
public int? BirthDay { get; set; }
[QueryDbField(Template = "(FirstName LIKE {Value} OR LastName LIKE {Value} OR PreferredName LIKE {Value})", ValueFormat = "%{0}%", Field = "ID")]
public string NameSearch { get; set; }
[QueryDbField(Template = "(FirstName LIKE {Value} OR LastName LIKE {Value} OR PreferredName LIKE {Value} OR Department.Name LIKE {Value} OR Title.Name LIKE {Value})", ValueFormat = "%{0}%", Field = "ID")]
public string BasicSearch { get; set; }
[QueryDbField(Template = "({Field} LIKE {Value})", Field = "EmployeeTypeName", ValueFormat = "%{0}%")]
public string EmployeeTypeSearch { get; set; }
[QueryDbField(Template = "({Field} LIKE {Value})", Field = "DepartmentName", ValueFormat = "%{0}%")]
public string DepartmentSearch { get; set; }
[QueryDbField(Template = "({Field} LIKE {Value})", Field = "TitleName", ValueFormat = "%{0}%")]
public string TitleSearch { get; set; }
}
Support for wildcard custom field lists was added in this commit where you can specify all fields of the primary or joined table by adding a .* suffix, e.g:
?fields=id,departmentid,department,employee.*
It essentially serves as a substitute placeholder which will be replace it with all fields in the specified table.
This change is available from v4.0.55 that's now available on MyGet.

MVC using multiple tables , 2 generated with code first and one with DB first

I am new to MVC and i think someone answered this question before , so i apologize for re-posting it.
I've been a form based programmers for years , and now i am working on an MVC project for the first time, last 3 weeks i read a lot of books, articles, tutorials and watched a lot of videos about MVC.
Here is my question:
- I have 3 tables: Tasks, Customer and Employee
Each task has 1 customer and one employee assigned to it. I generated the Tasks table from an existing table i have on a SQL DB , but i followed "Code-First" to create the employee and Customer tables. I am not sure if i did the right relationships between those table. What i want to do is to display all tasks + the userNAME + CustomerName instead of UserID and CustomerID.
Here are my models:
Tasks:
public partial class Tasks
{
public string TaskID { get; set; }
public string Name { get; set; }
public System.DateTime StartDate { get; set; }
public Nullable<System.DateTime> DueDate { get; set; }
public Nullable<int> Complete { get; set; }
public string Description { get; set; }
public Nullable<int> Priority { get; set; }
public string Status { get; set; }
public Nullable<System.DateTime> AssignementDate { get; set; }
public Nullable<System.DateTime> CreationDate { get; set; }
[ForeignKey ("Employee")]
public string EmployeeID { get; set; }
public virtual ApplicationUser _User { get; set; }
[ForeignKey("Customer")]
public string CustomerID { get; set; }
public virtual CustomerModel _Customer { get; set; }
}
Customer:
public class CustomerModel
{
[Key]
public String ID { get; set; }
public String Number { get; set; }
}
Employee
public class EmployeeModel
{
[Key]
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Also How to access the employee first name from my Tasks controller.
Last question: is it ok to mix between models (Some code-first and some DB-first) Or should i follow one pattern.
Thanks a lot
You can use both pattern, but I recommend you my approach that you use CodeFirst, create entites to store data and viewmodels to display data:
public class Task
{
public int TaskID { get; set; }
//your other properties here...
public int EmployeeId { get; set; }
public int UserId { get; set; }
public int CustomerId { get; set; }
}
And in client lawyer, create ViewModel for Task model:
public class TaskViewModel
{
public Task Task { get; set; }
public EmployeeModel Employee { get; set; }
public ApplicationUser User { get; set; }
public CustomerModel Customer { get; set; }
}
In your GetTask() (Or LoadTasks()) method fill this view model:
public TaskViewModel GetTask(int id)
{
TaskViewModel model = new TaskViewModel();
model.Task = _db.GetTaskById(id);
model.Employee = _db.GetEmployeeById(model.Task.EmployeeId);
model.User = _db.GetUserById(model.Task.UserId);
model.Customer = _db.GetCustomerById(model.Task.CustomerId);
return model;
}
And now, you can get all data you want related to a task:
TaskId, TaskName, Created user's name + surname, Employee's name surname, Custemer's name + surname etc..

EF Code First - Many To Many

I have a problem with devising a many to many relationship in code first. EF is creating the Junction table and associating the Fk's as I would expect, however when i try to access the User's MailingList collection, there are no entries.
I've implemented test data on Initialise via Seeding, the data is al present in the database.
I think the problem lies with the constructors for Users and MailingLists, but I'm uncertain. I want to be able to navigate the navigational property of User.MailingLists.
var user = db.Users.Find(1);
Console.WriteLine("{0}", user.EmailAddress); //This is Fine
Console.WriteLine("{0}", user.Address.PostCode); /This is Fine
foreach (MailingList ml in user.MailingLists) // this is 0
{
Console.WriteLine("{0}", ml.Name);
}
My model is below:-
public class User : IEntityBase
{
public User()
{
MailingLists = new List<MailingList>();
}
public int Id { get; set; }
public string Forename { get; set; }
public string Surname { get; set; }
public string EmailAddress { get; set; }
public DateTime? DateLastUpdated { get; set; }
public DateTime DateCreated { get; set; }
public bool IsDeleted { get; set; }
public virtual Address Address { get; set; }
public ICollection<MailingList> MailingLists { get; set; }
}
public class MailingList : IEntityBase
{
public MailingList()
{
Users = new List<User>();
}
public int Id { get; set; }
public string Name { get; set; }
public DateTime? DateLastUpdated { get; set; }
public DateTime DateCreated { get; set; }
public bool IsDeleted { get; set; }
public ICollection<User> Users { get; set; }
}
public class Address : IEntityBase
{
public int Id { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
public string City { get; set; }
public string County { get; set; }
public string PostCode { get; set; }
public DateTime? DateLastUpdated { get; set; }
public DateTime DateCreated { get; set; }
public bool IsDeleted { get; set; }
}
Any suggestions welcome.
You are neither eager loading the MailingList entries with the query, nor fulfulling the requirements for a lazy loading proxy so there is no way EF can populate the collection.
To allow lazy loading, change the MailingList property to be virtual to allow the EF proxy to override it.
To use eager loading, use Include() (an extension method in System.Data.Entity) in the query to specify that the MailingList should be loaded.

Resources