I'm trying to map one class to two database tables. I have a Person Class that maps to a Person table and an Address table. My problem is I only want to select the Primary Address Line (IsPrimary = 1) of the Address table and I can't find or figure out how to do this.
I'm using Entity Framework v6 CodeFirst and I trying to create the EntityTypeConfiguration<T> class
The domain class is...
public class Person
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// Primary Address
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
public string AddressPostCode { get; set; }
}
and the database tables look like this...
Table: Person
Int PersonId (PK)
Varchar(20) FirstName Not Null
Varchar(20) LastName Not Null
Table: Address
Int AddressId (PK)
Int PersonId (FK)
Varchar(25) AddressLine1 Null
Varchar(25) AddressLine2 Null
Varchar(25) AddressLine3 Null
Varchar(10) PostCode Not Null
Bit IsPrimary Not Null
Basically one Person can have multiple addresses but only One Primary Address.
If you are using Entity Framework, probably you have these following classes with a one to many relation:
public class PersonEntity
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<AddressEntity> Addresses { get; set; }
}
public class AddressEntity
{
public int AddressId { get; set; }
public int PersonId { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
public string AddressPostCode { get; set; }
public bool IsPrimary{ get; set; }
}
And as you mentioned in you'r question, this is the person viewmodel:
public class PersonViewModel
{
public int PersonId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// Primary Address
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
public string AddressPostCode { get; set; }
}
Finally you can use the following linq code:
var result = ctx.PersonEntity
.Where(c => c.Addresses.FirstOrDefault(X = > X.IsPrimary == true)).ToList();
var personViewModels = result
.Select(c => new PersonViewModel{
PersonId = c.PersonId ,
FirstName = c.FirstName ,
LastName = c.LastName,
AddressLine1 = c.Addresses != null ? c.Addresses.FirstOrDefault().AddressLine1 : String.Empty ,
AddressLine2 = c.Addresses != null ? c.Addresses.FirstOrDefault().AddressLine2 : String.Empty ,
AddressLine3 = c.Addresses != null ? c.Addresses.FirstOrDefault().AddressLine3 : String.Empty });
Related
I'm using System.Linq.Dynamic.
Given this parent - child (collection) model below, is it possible use OrderBy Client based on createdDate property passing the Id of the specific Address to sort with? Alternatively, Client properties can be used for the main sort as well. It also has to be sorted by Last and First Name.
public class Client
{
public int Id { get; set; }
public string FirstName{ get; set; }
public string LastName { get; set; }
public string Description {get; set;}
public string Type {get; set;}
public virtual ICollection<Address> Addresses { get; set; }
}
public class Address
{
public int Id { get; set; }
public DateTime createdDate { get; set; }
public DateTime modifiedDate { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
}
Is there a generic way to do all the scenarios?
OrderBy(Client.Addresses.Where("Id = #0", idValue).CreatedDate + " ASC , LastName DESC, FirstName DESC")
OrderBy("Type DESC, LastName DESC, FirstName DESC")
When using System.Linq.Dynamic.Core, you should be able to use:
.OrderBy("Type DESC, LastName DESC, FirstName DESC")
See also : https://dynamic-linq.net/basic-simple-query#ordering-results
I have an Employee table that links employees to their contact info. I have it set up like so:
[ForeignKey("AddressId")]
public virtual Address Address { get; set; }
[ForeignKey("HomePhoneId")]
public virtual PhoneNumber HomePhone { get; set; }
[ForeignKey("WorkPhoneId")]
public virtual PhoneNumber WorkPhone { get; set; }
[ForeignKey("CellPhoneId")]
public virtual PhoneNumber CellPhone { get; set; }
When I try to load employees from the database, however, it automatically renames the columns, completely overriding the attributes:
Invalid column name 'PhoneNumber_Id'.
Invalid column name 'PhoneNumber_Id1'.
Invalid column name 'PhoneNumber_Id2'.
Invalid column name 'Address_Id'.
Why is it doing this?
As stated by #mcbowes, it is hard to tell without seeing the rest of your Employee class, but most likely you are missing the following in your class:
public int AddressId { get; set; }
public int HomePhoneId { get; set; }
public int WorkPhoneId { get; set; }
public int CellPhoneId { get; set; }
The IDs were all properly specified for each navigation property. It seems the problem had to do with the navigation properties on each PhoneNumber and Address object that linked back to the Employee. I don't need them for now, so removing those navigation properties corrected the issue.
As an expansion on #peinearydevelopment set up your PhoneNumber:
public class PhoneNumber
{
public PhoneNumber(string name, int areaCode, string number)
{
Name = name;
AreaCode = areaCode;
Number = number;
}
public int ID { get; set; }
public string Name { get; set; }
public int AreaCode { get; set; }
public string Number { get; set; }
}
}
Set up your Employee:
public class Person
{
public Person(string first, string last, PhoneNumber home, PhoneNumber cell)
{
First = first;
Last = last;
HomeNumber = home;
CellNumber = cell;
}
public int ID { get; set; }
public string First { get; set; }
public string Last { get; set; }
public int HomePhone_ID { get; set; }
public int CellNumber_ID { get; set; }
public virtual PhoneNumber HomeNumber { get; set; }
public virtual PhoneNumber CellNumber { get; set; }
}
}
And your Context
public class PersonContext : DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<PhoneNumber> PhoneNumbers { get; set; }
}
As you can see, relationships are maintained, but you do need to explicitly tell your application which fields hold the identifiers, not just which tables have the relationships.
I am trying to use Entity Framework 6 and POCOs against an existing database with the following structure:
Departments
DepartmentID UNIQUEIDENTIFIER NOT NULL PK
SortOrder INT NULL
Image IMAGE NULL
Status BIT NULL
LastUpdated DATETIME NOT NULL
UpdatedBy NVARCHAR(10) NULL
Approved BIT NOT NULL
ApprovedBy NVARCHAR(10) NULL
ApprovedDate DATETIME NULL
ParentDepartment UNIQUEIDENTIFIER NULL
DepartmentDescriptions
DepartmentID UNIQUEIDENTIFIER NOT NULL PK, FK
LocaleID INT NOT NULL PK, FK
Description NVARCHAR(50) NOT NULL
Locales
LocaleID INT NOT NULL PK
ShortString NVARCHAR(10) NOT NULL
Description NVARCHAR(50) NOT NULL
Status BIT NOT NULL
My classes are:
public class Department
{
[Key]
public Guid DepartmentID { get; set; }
public Int32? SortOrder { get; set; }
public Byte[] Image { get; set; }
public Boolean Status { get; set; }
public DateTime LastUpdated { get; set; }
public String UpdatedBy { get; set; }
public Boolean Approved { get; set; }
public String ApprovedBy { get; set; }
public DateTime ApprovedDate { get; set; }
public Guid? ParentDepartment { get; set; }
// Navigation Properties
public virtual ICollection<DepartmentDescription> DepartmentDescriptions { get; set; }
public Department()
{
DepartmentDescriptions = new HashSet<DepartmentDescription>();
}
}
public class DepartmentDescription
{
[Key]
public Guid DepartmentID { get; set; }
public Int32 LocaleID { get; set; }
public String Description { get; set; }
// Navigation Properties
[ForeignKey("DepartmentID"), Required]
public virtual Department Department { get; set; }
[ForeignKey("LocaleID"), Required]
public virtual Locale Locale { get; set; }
}
public class Locale
{
[Key]
public Int32 LocaleID { get; set; }
public String ShortString { get; set; }
public String Description { get; set; }
public Boolean Status { get; set; }
// Navigation Properties
public virtual ICollection<DepartmentDescription> DepartmentDescriptions { get; set; }
public Locale()
{
DepartmentDescriptions = new HashSet<DepartmentDescription>();
}
}
When I try to add a new Department to the context I get:
*Unable to cast object of type 'System.Collections.Generic.HashSet`1[DepartmentDescription]' to type 'DepartmentDescription'.*
The code to add a new department (paraphrased) is:
Department _department = new Department
{
DepartmentID = new Guid("aed99956-c3e1-44a7-b09a-00169f64bdff"),
Status = true,
SortOrder = 320,
Image = null,
Approved = true,
ApprovedBy = "Import",
ApprovedDate = Convert.ToDateTime("11/22/2016 3:40:50PM"),
LastUpdated = Convert.ToDateTime("11/22/2016 3:40:50PM"),
UpdatedBy = Import
};
DepartmentDescription _description = new DepartmentDescription
{
DepartmentID = new Guid("aed99956-c3e1-44a7-b09a-00169f64bdff"),
LocaleID = 1033,
Description = "Department Description"
};
_department.DepartmentDescriptions.Add(_description);
context.Departments.Add(_department);
I'm sure I'm doing something that will deserve a facepalm, but I've been staring at this too long to see what I'm missing. Any suggestions would be greatly appreciated!
The DepartmentDescriptions table has a composite primary key which isn't represented by the DepartmentDescription class. As a result, the DbContext is trying to do its magical ORM stuff with POCOs that don't map to the database schema properly.
Using DataAnnotations, the DepartmentDescription class should look like this:
public class DepartmentDescription
{
[Key]
[Column(Order = 1)]
public Guid DepartmentID { get; set; }
[Key]
[Column(Order = 2)]
public Int32 LocaleID { get; set; }
public String Description { get; set; }
// Navigation Properties
[ForeignKey("DepartmentID"), Required]
public virtual Department Department { get; set; }
[ForeignKey("LocaleID"), Required]
public virtual Locale Locale { get; set; }
}
I'm working on Employee Model, it contains all the information about the Employee already I posted the same in How to use the DTO efficiently based on Scenario in C#. How could I share the single property for the multiple groups using Category attribute c#.
For Example:
public class Employee
{
public int EmployeeId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public string HomePhone { get; set; }
public string MobilePhone { get; set; }
}
I'm having the following four methods for fetching records of Employee
public Employee GetEmployeeName(int id)
{
// The return should contain only FirstName, MiddleName and LastName.
// The rest of the properties should be non-accessable (i.e., Private)
}
public Employee GetEmployeeContacts(int id)
{
// The return should contain only EmailAddress, HomePhone and MobilePhone.
// The rest of the properties should be non-accessable (i.e., Private)
}
public Employee GetEmployeeNameEmail(int id)
{
// The return should contain only FirstName, MiddleName, LastName and EmailAddress.
// The rest of the properties should be non-accessable (i.e., Private)
}
public Employee GetEmployee(int id)
{
// It should return the entire Employee object
}
How could I achieve this? could you please any one help in this regards.
A sample, this is the common use for DTO:
public class EmployeeNameDto
{
public int EmployeeId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
public EmployeeNameDto GetEmployeeName(int id)
{
Employee emplpoyee = employeeRepository.Find(id):
return new EmployeeNameDto() {
EmployeeId = emplpoyee.EmployeeId,
FirstName = emplpoyee.FirstName,
MiddleName = emplpoyee.MiddleName,
LastName = emplpoyee.LastName
};
}
Or
public class Employee
{
public int EmployeeId { get; set; }
public string FirstName { get;
set {
if (condition == false)
throw new Exception(" is Read Only !")
}
}
public string MiddleName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public string HomePhone { get; set; }
public string MobilePhone { get; set; }
}
Edited
I am trying to set up a many-to-one relationship on two tables I have got but I am unable to manage to make it work. I tried different options but I end up retrieving records of only one table.
Below is my table structure:
Customer
[Table("Customer")]
public class CustomerList
{
[Key]
public int CustomerID { get; set; }
public int Number { get; set; }
public string Surname { get; set; }
public string Forename { get; set; }
public DateTime? DateOfBirth { get; set; }
public int? MembershipTypeID { get; set; }
public MembershipTypeList MembershipType { get; set; }
public string Name;
public string EmailAddress { get; set; }
}
MembershipType
[Table("MembershipType")]
public class MembershipTypeList
{
[Key]
public int? MembershipTypeID { get; set; }
public string Name { get; set; }
//public virtual CustomerList Customer { get; set; }
}
Result
CustomerID 56
Number 52
Surname Antonelli
Forename Renny
DateOfBirth 1945-02-19
MembershipTypeID 1
EmailAddress Mr#test.com
Name NULL
Expected
CustomerID 56
Number 52
Surname Antonelli
Forename Renny
DateOfBirth 1945-02-19
MembershipTypeID 1
EmailAddress Mr#test.com
Name Blue ---> from membershiptype table