How to populate nested object in model? - c#

I'm creating a database first web api using entity framework. I created my models by creating ADO.NET Entity Models that were populated automatically with the fields on the tables that I selected. I want to be able to take some of those fields and group them in a custom object so when the xml is displayed, they are displayed as a child node.
An example is if I had the class with the following attributes
public class Person
{
public string firstname{get; set;}
public string lastname{get; set;}
public string street{get; set;}
public string city{get; set;}
public string zip{get; set;}
}
I want it to be something like this instead
public class Person
{
public string firstname{get; set;}
public string lastname{get; set;}
public string address{get; set;}//where address contains street, city, and zip
}
How would I go about in implementing this new Person class and populating the data of the custom object with my dbcontext

It is impossible to change three string properties to the one string property. How you can divide Address property to the street city and zip for example in case when street has two words?
You can create Address class (with three properties) and use it your Person class. But you will have problems when you try to regenerate/update your model - in such case is better to use code first approach.

Belongs-to Relationship
I think what you're looking for is a relationship between Person and a new class called Address.
To reference your new Address class inside Person, you would do the following:
public class Person
{
...
public Guid AddressId { get; set; }
public Address { get; set; }
}
Entity Framework will then associate an Address with the given AddressId with a Person.
Inside Address you can do something like this:
public class Address
{
public string City { get; set; }
public string Street { get; set; }
...
}
Eager Loading
To make sure an Address is loaded when a Person is loaded, you can use Entity Framework's Eager Loading capabilities, such as:
context.Person.Include(x => x.Address)

Use enumerable List like
public class Person
{
public string firstname{get; set;}
public string lastname{get; set;}
public List addresses{ get; set; }
}
public class Address
{
public string street{get; set;}
public string city{get; set;}
public string zip{get; set;}
}

Related

AutoMapper with nested objects and container class

I'm developing an API with .NET core and using AutoMapper.
all the API responses will be wrapped with a data element in the JSON response like below example
GET User
{
"data" {
"id" : 1,
"user_name": "abc"
"countryr" : {
"id" : 1348,
"code" : "USA"
}
}
}
So we have an entity for User and Country
public partial class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public virtual Country country { get; set; }
}
public partial class Country
{
public int Id { get; set; }
public string Code{ get; set; }
}
To map entities to DTO we have below reponseDTO
public class GetUserDTO {
public User data {get; set;} // To wrap reponse with data
}
public class UserDto {
public int id {get; set;}
public String user_name {get; set;}
public Country country {get; set;}
}
public class CountryDto {
public int id {get; set;}
public String code {get; set;}
}
As per my understanding , I should map the entity User to the UserDTO and Country entity to CountryDTO but what about GetUserDTO class itself? it basically contains other entities so the class itself cannot be mapped to anything it acts like a container.
So below what I did so far which is not correct
public class UserProfile : AutoMapper.Profile
{
public MappingProfile()
{
CreateMap<User, GetUserDTO>();
CreateMap<User, UserDto>()
.ForMember(userDto => userDto.user_name, map => map.MapFrom(user => user.FirstName))
CreateMap<Country, CountryDto>();
}
}
Json response
{
"data" : null
}
What to do for such situations?
You should not refer your entity classes in your DTO classes. You might want to change the DTO as below.
public class GetUserDTO {
public UserDto data {get; set;} // To wrap reponse with data
}
public class UserDto {
public int id {get; set;}
public string user_name {get; set;}
public CountryDto country {get; set;}
}
public class CountryDto {
public int id {get; set;}
public string code {get; set;}
}
And then in the Mapper profile, you need to explicitly map each property as cases are different(AutoMapper will map without explicity map if the names are exactly the same. In your example, there is a case difference)
And then remove the below line from the MapperProfile as there is no mapping from the User class to GetUserDTO class. This is the reason you are not getting any output.
CreateMap<User, GetUserDTO>();
While getting the data, you should create a new instance of GetUserDTO class and set the property "data" from the result of mappaing of the User object.
This will get you the output.

Entity Framework code first for object with collection of properties

I'm using C# and .NET Core with MySql and Entity Framework.
I have an object with a collection of properties. Like this:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<Property> Properties { get; set; }
}
public class Property
{
public int Id { get; set; }
public string Name { get; set; }
public object Value { get; set; }
}
In this case in the database, I should have tables Products, Properties (where property is described, like name and some additional info), and link table ProductProperties, storing product Id, property Id and Value.
But I can't figure out how to do this with a code-first approach.
How could I implement it with code first?
Is it a good way to create one more entity PropertyValue and store it under Product?
Something like this should give you a 1-to-many relationship, although you need to give Value a type, like string to store it in the database, often for dynamic solutions like this you would then maybe add a type to specify the type to deserialize into, but since you then deserialize anyway you could also just add things as json or something else in the db.
public class Product
{
public int Id {get; set;}
public string Name{get; set;}
public ICollection<Property> Properties{get; set;}
}
public class Property
{
public int Id {get; set;}
public string Name {get; set;}
public string Value {get; set;}
public int ProductId {get; set;}
}
Unless you are making a very dynamic system, it doesn't seem right to have the properties as a table, depends a lot of what you are making, and maybe key-value db might be a better tool for the job if thats what your main problem is, as with most complicated things, it depends.
This example is a convention based approach, which is why properties like ProductId have to be called exactly that. You can look at EntityTypeConfigurations if you want more control of names and relationships and such, or use data annotations to achieve the same job.
Ok so create a table like this:
public class ProductProprties
{
public int ProductId {get; set;}
public Product Product {get;set;}
public int PropertyId {get; set;}
public Property Property {get;set;}
//other props
}
If you are using EntityFramework Core, then you have to add this to your databse context as well:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ProdcutProprties>().HasKey(x => new { x.ProductId , x.PropertyId });
}

AutoMap a property to property of sub-property

I have this simple data model:
// Model
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
.... Another values here ....
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
.... Another values here ....
}
// ViewModel
public class PersonViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
}
I want to map (using AutoMapper) the values of PersonViewModel to the corresponding properties (where AutoMapper discovers if the property should be in the root object or inside the sub-object). Keeping in mind, AutoMapper should not create neither Person object nor Address (the objects must be created manually to fill another properties before auto mapping), and AutoMapper uses the already existed objects. For example:
var addressObj = new Address
{
... Filling some values...
};
var personObj = new Person
{
Address = addressObj;
... Filling some values...
};
mapper.Map(personViewModelObj, personObj); // How to make this work for both Person and Address properties?
How can I get that auto mapping to work for both person properties and address properties?
Should I add two mapping rules (for address and for person), and execute mapper.Map() twice?
Using #Jasen comments I got it working. The main problem was that I am mapping in a reversed direction. This sentence in official documentation solves the problem:
Unflattening is only configured for ReverseMap. If you want unflattening, you must configure Entity -> Dto then call ReverseMap to create an unflattening type map configuration from the Dto -> Entity.
Here is the link:
https://github.com/AutoMapper/AutoMapper/blob/master/docs/Reverse-Mapping-and-Unflattening.md
In other words, to get unflattering to work, I have (or must) to map in this direction:
CreateMap<HierarchicalObject, FlattenedObject>()
.ReverseMap();

CustomAttribute with property that is a AttributeTarget property name as string

I want to change my CustomAttribute usage in this way, I'm using it to refer to the search parameters of an autocomplete dropdown
now:
[EntitySearchDropBox(Id="Id",SearchColumns="Name")]
public virtual class MyTarget
But i hate strings for defining entity properties and the best solution for me is passing AttributeTarget property without writing free strings.
[EntitySearchDropBox(Id=MyTarget.Id,SearchColumns=MyTarget.Name)]
public virtual class MyTarget
MyTarget example
public class MyTarget{
public int Id {get; set;}
public string Name {get; set;}
public string otherProperty { get; set; }
//etc..
}

Multidimensional navigational properties in Entity Framework 6 Code First

I am trying to figure out if something like this this possible:
Suppose I have the following model of a sports team:
Person( ID, Name, Roles)
Role ( Person, Title) ex: Owner, Player, Coach, ... a Person can have more than one role ( A player can be an owner for example)
Now lets say that I want to create a team Model something like this:
public class Team {
public string Name {get; set; }
public virtual Dictionary<Role, List<Person>> TeamMemebers {get; set; }
}
vs doing something like this:
public class Team {
public string Name {get; set; }
public virtual List<Person>> Players {get; set; }
public virtual List<Person>> Owners {get; set; }
public virtual List<Person>> Coaches {get; set; }
...
}
I am trying to figure out if this is possible?
Thanks
If you need only select on this property then I would create one partial class for model (as in your 2nd snippet) and another one for custom methods and properties.
And there I would add
[System.ComponentModel.DataAnnotations.Schema.NotMapped]
Dictionary<Role, List<Person>> TeamMemebers
{
get
{
// return select mapped to dictionary
}
}

Categories

Resources