ASP.NET Core Entity Framework Core inheritence - c#

There is a model class called Review.
ReviewModel is used from StoreModel and Menu model.
In StoreModel.cs
[Table ("Stores")]
public class StoreModel
{
[Key]
public int Id { get; set; }
public string StoreName { get; set; }
public string StoreShortDescription { get; set; }
public string StoreFullDescription { get; set; }
public string StoreAddress { get; set; }
public ICollection<MenuModel> Menus { get; set; }
public ICollection<ReviewModel> Reviews { get; set; }
public StoreModel ()
{
Menus = new Collection<MenuModel> ();
Reviews = new Collection<ReviewModel> ();
}
}
in MenuModel.cs
[Table ("Menus")]
public class MenuModel
{
[Key]
public int Id { get; set; }
public string MenuName { get; set; }
public string MenuShortDescription { get; set; }
public string MenuThumbnailUrl { get; set; }
public int MenuPrice { get; set; }
public ICollection<ReviewModel> MenuReviews { get; set; }
public MenuModel ()
{
MenuReviews = new Collection<ReviewModel> ();
}
}
In this case, how should I implement this?
Create a base ReviewModel class and have 2 subclass (StoreReview, MenuModel)
or
Use ReviewModel for both StoreModel and MenuModel (how?)
or
thoughts?

If the ReviewModel properties are the same in both (StoreModel and MenuModel) there is nothing special to do, just use ReviewModel as it is being used in your shown code for both models.
In any case, just add an enum property to ReviewModel to know wether it is a StoreModelReview or a MenuModelReview.
Your ReviewModel might look like this: (creating many 2 many relationship)
[Table ("Reviews")]
public class ReviewModel
{
[Key]
public int Id { get; set; }
public ReviewEnum Type { get; set; }
public ICollection<MenuModel> Menus{ get; set; }
public ICollection<StoreModel> Stpres{ get; set; }
}

Related

C# find child class via parent class

I have 3 classes PropiedadEspecificaFilm, PropiedadEspecificaBook and PropiedadEspecificaMusic which inherit from Product.
public partial class PropiedadEspecificaBook : Product
{
public string ISBN { get; set; }
public string author { get; set; }
public long productId { get; set; }
//Equals
//ToString
}
public partial class PropiedadEspecificaMusic : Product
{
public string name { get; set; }
public string artist{ get; set; }
public long productId { get; set; }
//Equals
//ToString
}
public partial class PropiedadEspecificaMusic : Product
{
public string name { get; set; }
public string artist{ get; set; }
public long productId { get; set; }
//Equals
//ToString
}
public partial class Product
{
public Product()
{
this.OrderLines = new HashSet<OrderLine>();
this.Comments = new HashSet<Comment>();
}
public long id { get; set; }
public string productName { get; set; }
public decimal price { get; set; }
public System.DateTime releaseDate { get; set; }
public short stock { get; set; }
public long categoryId { get; set; }
}
Is there a way to know which one of the PropiedadEspecifica has the productId I am looking for?
Yes, if all products share a property you should declare that in the parent class and not in the children. The children should only have the properties that differ from the parent class.
I also strongly suspect you do not need to mark your classes as partial (that is used if you want to split your class definition up, it is not intended for inheritance).
I also changed so the public properties are capitalized since that is the general convention for c# naming.
public class PropiedadEspecificaBook : Product
{
public string ISBN { get; set; }
public string Author { get; set; }
}
public class PropiedadEspecificaMusic : Product
{
public string Name { get; set; }
public string Artist{ get; set; }
}
public class PropiedadEspecificaMusic : Product
{
public string Name { get; set; }
public string Artist{ get; set; }
}
public class Product
{
public Product()
{
this.OrderLines = new HashSet<OrderLine>();
this.Comments = new HashSet<Comment>();
}
public long Id { get; set; }
public string ProductName { get; set; }
public decimal Price { get; set; }
public System.DateTime ReleaseDate { get; set; }
public short Stock { get; set; }
public long CategoryId { get; set; }
public long ProductId { get; set; }
}
I solved it by adding a virtual Dictionary<String, String> FindPropiedadEspecificaMethod() in Product. And then Overriding in each PropiedadEspecifica. Sorry because the problem was bad explained.

Automapper configuration falls short on partial class?

I have following AccountDetailRecord class to be mapped to the AccountDetailDto with the following configuration but somehow I am missing something in mapping the partial classes.
services
.AddSingleton(new MapperConfiguration(cfg =>
{
cfg.CreateMap<AccountDetailRecord, AccountDetailDto>().ReverseMap();
cfg.CreateMap<AddressRecord, AccountDetailDto.AddressDto>().ReverseMap();
}).CreateMapper())
source:
internal class AccountDetailRecord
{
public Guid Id { get; set; }
public string EstablishmentNumber { get; set; }
public string Name { get; set; }
}
internal class AddressRecord
{
public Guid Id { get; set; }
public string City { get; set; }
public string County { get; set; }
public int AddressTypeId { get; set; }
public string AddressTypeDescription { get; set; }
}
destination:
public partial class AccountDetailDto
{
public Guid Id { get; set; }
public string EstablishmentNumber { get; set; }
public string Name { get; set; }
public List<AddressDto> Addresses { get; set; }
}
public partial class AccountDetailDto
{
public class AddressDto
{
public Guid Id { get; set; }
public string City { get; set; }
public string County { get; set; }
public AddressTypeDto AddressType { get; set; }
}
}
public partial class AccountDetailDto
{
public class AddressTypeDto
{
public int Id { get; set; }
public string Description { get; set; }
}
}
but in the result the values of the AddressType.
what am I missing in configuration?
According to your classes properties, what you need is to reverse the mapping, so AutoMapper will be able to unflatten your AddressTypeId and AddressTypeDescription source properties into an AddressTypeDto object.
As the documentation states:
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
So you simply need to swap your mapping declaration to:
cfg.CreateMap<AccountDetailDto.AddressDto, AddressRecord>().ReverseMap();

Nested Collection Mapping in Automapper

Am trying to map nested collections using automapper and I have done the basic setup and configuration. When I try to do the map it the nested values are coming as null. I have tried to follow few posts and put together something. I want the list to have a hierarchy instead of flattening. Any help around this would be great.
Source Entities:
public class OuterEntity
{
public int ID { get; set; }
public string Name { get; set; }
public List<InnerEntity> InnerEntityList { get; set; }
}
public class InnerEntity
{
public int InnerId { get; set; }
public string InnerName { get; set; }
public List<InnerMostEntity> InnerMostList { get; set; }
}
public class InnerMostEntity
{
public int InnerMostId { get; set; }
public string InnerMostName { get; set; }
public DateTime ModifiedDate { get; set; }
}
Destination Entities:
public class OuterEntityDTO
{
public int ID { get; set; }
public string Name { get; set; }
public List<InnerEntity> InnerEntityList { get; set; }
}
public class InnerEntityDTO
{
public int InnerId { get; set; }
public string InnerName { get; set; }
public List<InnerMostEntity> InnerMostList { get; set; }
}
public class InnerMostEntityDTO
{
public int InnerMostId { get; set; }
public string InnerMostName { get; set; }
public DateTime ModifiedDate { get; set; }
}
Controller Class:
public List<OuterEntityDTO> GetAll()
{
var outerEntityList = myRepo.GetAll(); //Type of List<OuterEntity>
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<OuterEntity, OuterEntityDTO>().ReverseMap();
cfg.CreateMap<InnerEntity, InnerEntityDTO>().ReverseMap();
cfg.CreateMap<InnerMostEntity, InnerMostEntityDTO>().ReveseMap();
});
config.AssertConfigurationIsValid();
var innerMostDTO = Mapper.Map<List<OuterEntity>,List<OuterEntityDTO>>(outerEntityList);
//The inner list at first level itself is null.
return innerMostDTO;
}
Am trying to achieve this in DOT NET Core. Autommaper version is 6.1.1
I think you should have a wrong class hierarchy in DTO classes, as you have
public List<InnerMostEntity> InnerMostList { get; set; }
in public class InnerEntityDTO, you should write it as
public List<InnerMostEntityDTO> InnerMostList { get; set; }

Creating ViewModel that contains parent class properties in ASP.NET MVC

I am trying to understand how to create a ViewModel that contains properties from a class in my domain model as well as properties from a parent class.
I want to have a ViewModel that contains all of the LoadSession properties and the TradingPartner Description, but I'm not sure how to map this all up in the ViewModel. Any help or advice would be greatly appreciated.
This is my main class I'm accessing named LoadSession:
public partial class LoadSession
{
public LoadSession()
{
this.AcceptedTransactions = new HashSet<AcceptedTransaction>();
this.RejectedTransactions = new HashSet<RejectedTransaction>();
}
public int LoadSessionId { get; set; }
public int Import { get; set; }
public string FilePath { get; set; }
public string TradingPartnerBatchId { get; set; }
public System.DateTime Started { get; set; }
public int RecordsOnFile { get; set; }
public int RecordsAfterGroupFilter { get; set; }
public int RecordsAccepted { get; set; }
public int RecordsRejected { get; set; }
public System.DateTime Completed { get; set; }
public bool Success { get; set; }
public Nullable<int> Extract { get; set; }
public virtual ICollection<AcceptedTransaction> AcceptedTransactions { get; set; }
public virtual Extract Extract1 { get; set; }
public virtual Import Import1 { get; set; }
public virtual ICollection<RejectedTransaction> RejectedTransactions { get; set; }
}
The Import property is a foreign key for this Import class (Import = ImportId):
public partial class Import
{
public Import()
{
this.GroupPlans = new HashSet<GroupPlan>();
this.ImportGroups = new HashSet<ImportGroup>();
this.MatchingGroups = new HashSet<MatchingGroup>();
this.LoadSessions = new HashSet<LoadSession>();
}
public int ImportId { get; set; }
public string Description { get; set; }
public int Format { get; set; }
public int Interface { get; set; }
public virtual Interface Interface1 { get; set; }
public virtual Format Format1 { get; set; }
public virtual ICollection<GroupPlan> GroupPlans { get; set; }
public virtual ICollection<ImportGroup> ImportGroups { get; set; }
public virtual ICollection<MatchingGroup> MatchingGroups { get; set; }
public virtual ICollection<LoadSession> LoadSessions { get; set; }
}
The Interface property is a foreign key for this Interface class (Interface = InterfaceId):
public partial class Interface
{
public Interface()
{
this.Extracts1 = new HashSet<Extracts1>();
this.Imports = new HashSet<Import>();
}
public int InterfaceId { get; set; }
public string Description { get; set; }
public int TradingPartner { get; set; }
public virtual ICollection<Extracts1> Extracts1 { get; set; }
public virtual ICollection<Import> Imports { get; set; }
public virtual TradingPartner TradingPartner1 { get; set; }
}
And the TradingPartner property is a foreign key for this TradingPartner class (TradingPartner = TradingPartnerId):
public partial class TradingPartner
{
public TradingPartner()
{
this.Interfaces = new HashSet<Interface>();
}
public int TradingPartnerId { get; set; }
public string Description { get; set; }
public virtual ICollection<Interface> Interfaces { get; set; }
}
Well, those are all your domain objects right...
Create a repository that takes your Domain object and transforms then to into a view model with the properties you need...
I am not sure what it is your view needs, but from your statements you state that you want properties of Load session + TradingPartner.Description So create something like this...
public class LoadSessionTradingPrtNrVM
{
public LoadSession()
{
this.AcceptedTransactions = new HashSet<AcceptedTransaction>();
this.RejectedTransactions = new HashSet<RejectedTransaction>();
}
public int LoadSessionId { get; set; }
public int Import { get; set; }
public string FilePath { get; set; }
public string TradingPartnerBatchId { get; set; }
public System.DateTime Started { get; set; }
public int RecordsOnFile { get; set; }
public int RecordsAfterGroupFilter { get; set; }
public int RecordsAccepted { get; set; }
public int RecordsRejected { get; set; }
public System.DateTime Completed { get; set; }
public bool Success { get; set; }
public Nullable<int> Extract { get; set; }
public string Description { get; set; }
public virtual ICollection<AcceptedTransaction> AcceptedTransactions { get; set; }
public virtual Extract Extract1 { get; set; }
public virtual Import Import1 { get; set; }
public virtual ICollection<RejectedTransaction> RejectedTransactions { get; set; }
}
To get from Domain models to ViewModels you would use a repository, or some other pattern that takes what you get from your database and transforms it into what you need for your views.
This is kind of raw, but the theory should hold...
public class DataRepository {
LoadSessionTradingPrtNrVM TransformToVM(LoadSession inputA, TradingPartner inputB){
LoadSessionTradingPrtNrVM newOBJ = new LoadSessioNTradingPrtNrVM();
newOBJ.LoadSessionId = ipnutA.LoadSessionID;
newOBJ.Import = inputA.Import
//Here is the property from your Transform object
newOBJ.Description = inputB.Description
//... Continue to transform one object into the other...
//You could add as many members from as many different objects as you want into
//Your view model following that pattern.
}
}
I didn't have a chance to run this through a C# compiler, but you should get the general idea. I am sure there is a more elegant pattern that can accomplish the same thing. But this is a decent solution off the top of my head.
Another option is to include the domain model objects as properties in the view model. For example:
// View model.
public class UserViewModel
{
public AddressModel Address; // Assuming "AddressModel" is a doman model.
public string FirstName;
public string LastName;
}
And in the view you can access the properties as:
#Model.Address.AddressLine1
#Model.Address.City
// etc...
The Html helpers handle this just fine, but if you are manually naming inputs in your view don't forget to adjust those names to match.

TPH Approach Service implementation

What is the best aproach to develop a TPH based entity with Entity Framework, for example, if I have common fields in an Ads website, and specific ones:
public class Ad
{
// Primary properties
public int Id { get; set; }
public string Title { get; set; }
public string TitleStandard { get; set; }
public string Version { get; set; }
public string VersionStandard { get; set; }
public int Year { get; set; }
public decimal Price { get; set; }
// Navigation properties
public Color Color { get; set; }
public Member Member { get; set; }
public Category Category { get; set; }
public IList<Feature> Features { get; set; }
public IList<Picture> Pictures { get; set; }
public IList<Operation> Operations { get; set; }
}
public class AdCar : Ad
{
public int Kms { get; set; }
public Model Model { get; set; }
public Fuel Fuel { get; set; }
}
public class AdBoat : Ad
{
public int Hours { get; set; }
public string Model { get; set; }
}
Do I have to build specific operations for every subclass:
CreateAdCar()
CreateAdBoat()
Or can I have something like:
CreateAdCommon() and CreateAdCar()
How can I split the two classes so I don't have to repeat all the code for the Car Ad class and Boat Ad class?

Categories

Resources