I am started using automapper in my simple project. I want to exactly following 'one-to-many-to-many' mapping :-
public class AppUser
{
public int Id { get; set; }
public string UniversityName { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Description { get; set; }
public int AppUserId { get; set; }
public AppUser AppUser { get; set; }
public ICollection<Postedpic> Postedpics { get; set; }
}
public class Postedpic
{
public int Id { get; set; }
public string Url { get; set; }
public string PublicId { get; set; }
public Post Post { get; set; }
public int PostId { get; set; }
}
Destination:
public class MemberDto
{
public int Id { get; set; }
public string UniversityName { get; set; }
public ICollection<PostDto> Posts { get; set; }
}
public class PostDto
{
public int Id { get; set; }
public string Description { get; set; }
public ICollection<PostedpicDto> Postedpics { get; set; }
}
public class PostedpicDto
{
public int Id { get; set; }
public string Url { get; set; }
public bool IsMain { get; set; }
}
For proceed with automapper I tried this:-
CreateMap<AppUser, MemberDto>()
.ForMember(dest=>dest.Posts,opt=>opt.MapFrom(src=>src.Posts.Select(x=>x.Description)))
.ForMember(dest=>dest.Posts,opt=>opt.MapFrom(src=>src.Posts.Include(x=>x.Postedpic).Select(x=>x.Postedpic.Url)))
.ForMember(dest=>dest.Posts,opt=>opt.MapFrom(src=>src.Posts.Include(x => x.Postedpic).Select(x=>x.Postedpic.PublicId)));
But I found this error:-
Also I don't understand my approach is right or wrong for proceeding automapper.
You have two issues here:
For the Include method, you need to import the right namespace:
using System.Data.Entity;
You then tell AutoMapper how to do its job. It's smart enough to map properties by name, so you don't need to do much here. You just need to tell it which types to map to:
CreateMap<Post, PostDto>();
CreateMap<PostedPic, PostedPicDto>();
CreateMap<AppUser, MemberDto>();
As for the context, it looks to me like you are using lazy loading and want to make sure the posts and pics are loaded. For this to work, you need to configure the original query with Include, prior to mapping. For instance:
var user = SomeContext.AppUsers
.Include(u => u.Posts)
.Include(u => u.Posts.Select(p => p.PostedPics))
.FirstOrDefault(u => u.Id == someId);
var userDto = mapper.Map<AppUser, MemberDto>(user);
Dont use automapper, or any other mapping framework. This is code smell.
Create an interface like:
public interface IMemberDtoCreator {
int GetId();
string GetUniversityName();
ICollection<PostDto> GetPosts();
}
public class MemberDto {
public int Id { get; set; }
public string UniversityName { get; set; }
public ICollection<PostDto> Posts { get; set; }
public MemberDto(IMemberDtoCreator creator) {
Id = creator.GetId();
UniversityName = creator.GetUniversityName();
Posts = creator.GetPosts();
}
}
public class AppUser : IMemberDtoCreator {
public int Id { get; set; }
public string UniversityName { get; set; }
public ICollection<Post> Posts { get; set; }
public int GetId() {
return Id;
}
public string GetUnivsersityName() {
return UniversityName;
}
public ICollection<Post> GetPosts(){
ICollection<PostDto> result = new ICollection<PostDto>();
foreach(Post post in Posts){
result.add(new PostDto(post)) // And repeat the interface implementation for PostDto and post, etc.
}
}
}
This is pseudo code, and I didn't check for compiling, but you get the idea, I am sure. This is better in every way imaginable.
(If you are worried about overwriting the implementation of your interfaces, simply write the implementations in a partial class. Then you can autogenerate the original "base" class forever, and never interrupt your interface implementations.
Can someone help my with business logic when I try to find products in my bd list with properties from ProductFilterVM or give my advice where I can find solution.
public class ProductFilterVM
{
public string? Name { get; set; }
// other properties relating to a product that you may want to display the view - e.g. Description
public IEnumerable<FilterCategoryVM>? FilterCategories { get; set; }
}
public class FilterCategoryVM
{
public int Id { get; set; }
public string? Name { get; set; }
public List<FilterSelectionVM>? Selections { get; set; }
}
public class FilterSelectionVM
{
public int Id { get; set; }
public string? Name { get; set; }
}
I'm Creating an Event Management asp.net core app, My Customer Entity is related with different Entities by many to many relations. know I want to filter my Customers depending on both Event Name and Main Category name Entities.
Here are my Entities
Customer
public class Customer
{
public int Id {get; set;}enter code here
public string Name { get; set; }
public IList<CustomerEvent> CustomerEvents { get; set; }
public IList<CustomerMainCategory> CustomerMainCategories { get; set; }
}
Event
public class Event
{
public int Id { get; set; }
public string EventName { get; set; }
public IList<CustomerEvent> CustomerEvents { get; set; }
}
CustomerEvent
public Class CustomerEvent
{
public int CustomerId { get; set; }
public Customer Customer { get; set; }
public int EventId { get; set; }
public Event Event { get; set; }
}
MainCategory
public class MainCategory
{
public int Id { get; set; }
public string MainCategoryName { get; set; }
public IList<CustomerMainCategory> CustomerMainCategories { get; set; }
}
CustomerMainCategory
public class CustomerMainCategory
{
public int CustomerId { get; set; }
public Customer Customer { get; set; }
public int MainCategoryId { get; set; }
public MainCategory MainCategory { get; set; }
}
I want to Filter Customers that have same main category in the specified event.
Thank You in advance!!
Something like this?
(untestet)
db.Customers.Where(
c => c.CustomerEvents.Any(ce => ce.Event.Id == x)
&& c.CustomerMainCategories.Any(mc => mc.MainCategory.Id == y)
).ToList();
I have Domain object ProductType. It contains parentproducttypeId column. If product type is a subset of another producttype that parentproducttypeId to set to that producttypeId.(ex: T-Shirt is a subset of Casual wears)
public class ProductType : IEntityBase
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int PerentProductTypeId { get; set; }
public int Active { get; set; }
public DateTime UpdatedOnUTC { get; set; }
}
In API view model I have two classes
public class ParentProductTypeModel
{
public int Id { get; set; }
public string Name { get; set; }
public List<ChildProductTypeModel> ChildProductTypeList { get; set; }
public ParentProductTypeModel()
{
ChildProductTypeList = new List<ChildProductTypeModel>();
}
}
public class ChildProductTypeModel
{
public int Id { get; set; }
public string Name { get; set; }
}
I need to Map returned List of Product Type to this ParentProductTypeModel List with setting all subset lists according to there parentproducttypeId. If parentproducttypeId equals to 0 it is parentproduct.
I am trying to set up a relationship where a Car can have multiple Testruns, as well as an optionally selected "active testrun".
public class Car
{
public int ID { get; set; }
public virtual TestRun ActiveTestRun { get; set; }
public virtual ICollection<TestRun> TestRuns { get; set; }
}
public class TestRun
{
public int ID { get; set; }
public double TopSpeed { get; set; }
public virtual Car ActiveCar { get; set; }
public virtual Car Car { get; set; }
}
I have been trying to use InverseProperties with or without ForeignKey-attributes but to no luck. What is the correct way to setup this kind of relation? TIA!
Ps. I think I tried mostly all of the combinations from this tutorial without getting it to work :(
http://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in-code-first.aspx
EDIT: The resulting DB-schema I would want is something like:
tbl_Cars:
ID, ActiveTestRunID[Nullable]
tbl_TestRuns:
ID, TopSpeed, CarID
This achieved the result that I wanted:
public class Car
{
public int ID { get; set; }
public int? ActiveTestRunID { get; set; }
public virtual TestRun ActiveTestRun { get; set; }
[InverseProperty("Car")]
public virtual ICollection<TestRun> TestRuns { get; set; }
}
public class TestRun
{
public int ID { get; set; }
public double TopSpeed { get; set; }
public int CarID { get; set; }
public virtual Car Car { get; set; }
}