Map one Class properties to two different class properties using Mapster - c#

I have 3 classes with the name of Employee, EmployeeTwo, and EmployeeThree, I wanted to map Employee to EmployeeTwo and Employee to EmployeeThree.
Following are the Classes.
I also have tried to define the AdaptMember attribute on the Employee Class property but it only defines one and I have to map it with two different.
Note: I cannot define any attribute to the EmployeeTwo and EmployeeThree classes because this comes from the API and it can be regenrate.
public class Employee
{
[AdaptMember(nameof(EmployeeTwo.EmployeeID))]
public int ID { get; set; }
[AdaptMember(nameof(EmployeeTwo.EmployeeName))]
public string Name { get; set; }
}
public class EmployeeTwo
{
public int EmployeeID { get; set; }
public string EmployeeName { get; set; }
}
public class EmployeeThree
{
public int EmployeeThreeID { get; set; }
public string EmployeeThreeName { get; set; }
}
Any help is really appriciated.

As I understand you, you want to make a custom object mapping using mapster.
If you want to make a custom mapping you need to create a class:
using Mapster;
namespace Application.Mapsters
{
public class Config : ICodeGenerationRegister
{
public void Register(CodeGenerationConfig config)
{
TypeAdapterConfig<Employee, EmployeeTwo>
.NewConfig()
.Map(dst => dst.EmployeeID, src => src.ID)
.Map(dst => dst.EmployeeName, src => src.Name);
}
}
}
For instance, follow this example to see how to make a custom mapping using mapster:
https://floatincode.net/2021/07/26/mapster-generate-dto-async-after-map-actions-dependency-injection/

Related

Automapper nested relationship "back" mapping

Let's say I have a nested DTO, like this (in reality it is a lot more complex):
public class OrderDTO
{
public int Id { get; set; }
public List<ItemDTO> Item { get; set; }
}
public class ItemDTO
{
public int Id { get; set; }
}
that maps to:
public class Order
{
public int Id { get; set; }
public List<Item> Item { get; set; }
}
public class Item
{
public int Id { get; set; }
public Order Order { get; set; }
}
When mapping from the OrderDTO down to Order, I would like that the Order property from Item references its order, as to make something like var order = item.Order; possible.
Is there any way I can do that when mapping? Also, is it possible to configure that for all my nested mappings?
Using BeforeMap you can save the parent object in context.Items and then use that value in a resolver for the parent reference. If you respect a naming convention, you can use ForAllMaps to apply it wherever you need.

Add xml attribute for property in DB First

I have:
Entity Framework DB first
public partial class Departments
{
public string Name_Department { get; set; }
public int Department_ID { get; set; }
}
When i was refreshed model all modify in file was cleared
I need:
How can i add attribute property to Serialize XML like:
[Serializable]
[XmlType(nameof(Departments))]
public partial class Departments
{
[XmlAttribute("Name_Department")]
public string Name_Department { get; set; }
[XmlAttribute("Department_ID")]
public int Department_ID { get; set; }
}
You have to make the generated properties private in the properties window. Then you have to create new public properties that reference the private properties and add the attributes to them. In the properties window you can also rename your now private properties so that you can name your public properties like the original ones:
Generated code:
public partial class Departments
{
private string Name_DepartmentCore { get; set; }
private int Department_IDCore { get; set; }
}
Custom code (in C# 7.0):
[Serializable]
[XmlType(nameof(Departments))]
public partial class Departments
{
[XmlAttribute("Name_Department")]
public string Name_Department {
get => Name_DepartmentCore;
set => Name_DepartmentCore = value;
}
[XmlAttribute("Department_ID")]
public int Department_ID {
get => Department_IDCore;
set => Department_IDCore = value;
}
}
Your class model is generated when you are using DB first, that is by design.
Solution 1. Microsoft is dropping support for database first, and edmx is depricated. One solution would be to use CODE FIRST instead. This would allow you to decorate your POCO classes with attributes.
Solution 2. Create a parallel model just for XML serialization.

MVC 4 EF database first Model constructor updates

I have created an MVC 4 application with EF db-first using ADO.NET Entity Data Model.
I've previously been adding data validation and updating constructors directly into the generated Model classes, but as I foresee these tables to be updated I don't want to have to add these all back in, plus I shouldn't be editing these auto generated classes anyway.
Using Metadata.cs and PartialClasses.cs from http://www.asp.net/mvc/tutorials/mvc-5/database-first-development/enhancing-data-validation I'm not sure the best way to update the default constructors for these Model classes.
Here's an example model, simplified.
Within .edmx
public partial class Campaign
{
public Campaign()
{
this.Fees = new HashSet<Fee>();
}
public int ID { get; set; }
public string Name { get; set; }
public string CreatedBy { get; set; }
public System.DateTime CreatedOnDate { get; set; }
public virtual ICollection<Fee> Fees { get; set; }
}
within ParticalClasses.cs [errors as the generated Modal class defines the default constructor]
[MetadataType(typeof(CampaignMetadata))]
public partial class Campaign
{
public Campaign()
{
this.Fees = new HashSet<Fee>();
// Non-Generated
this.CreatedOnDate = DateTime.Now;
}
}
I have other models I would also like to have other constructors with different parameters, so to simplify my question, where do I add constructors for DB first MVC as to no update the generated Model classes?
Not 100% sure about what you are trying to do, but I'll try to answer your question.
First of all, it seems that you are missing the point of the MVC: your link refers to view model validators, but you are talking about data models. Two VERY different things. There's nothing to validate in a data model - those change and are govern by what's going on in the database.
This is what I would do:
1) Create a data layer: this would hold all your entity classes.
2) Create a service layer: this will instantiate and populate the entity classes using either raw sql, or a pattern (repository pattern, for exam).
3) Create your website: this will hold your controllers, view models (they are the ones you want to validate) and views.
For your Campaign class:
public interface IEntity
{
object EntityID { get; set; }
}
public abstract class BaseEntity: IEntity
{
public abstract object EntityID { get; set; }
}
public class Campaign : BaseEntity
{
#region Properties
public int ID { get; set; }
public string Name { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOnDate { get; set; }
public virtual List<Fee> Fees { get; set; }
#endregion
#region BaseEntity Implementation
public override object EntityID
{
get { return this.ID; }
}
#endregion
#region Constructors
public Campaign()
{
this.CreatedOnDate = DateTime.Now;
this.Fees = new List<Fee>();
}
#endregion
}
//View model
//THIS is the class you want to validate
public class CampaignViewModel
{
#region Properties
public int ID { get; set; }
[StringLength(50)]
public string Name { get; set; }
[Required]
public string CreatedBy { get; set; }
public DateTime CreatedOnDate { get; set; }
public Fee AssociatedFee { get; set; }
#endregion
#region Constructors
public CampaignViewModel()
{ }
public CampaignViewModel(Campaign data)
{
this.ID = data.ID
this.Name = data.Name;
this.CreatedBy = data.CreatedBy;
this.CreatedOn = data.CreatedOn;
this.AssociatedFee = data.Fees.Where(x=>x.Active && x.ID == this.ID);
//Just an example
}
#endregion
}
Also, you could use Fluent Validation for a more in-depth separation of concerns. (http://fluentvalidation.codeplex.com/)

Entity Framework Many to many through containing object

I was curious if it is possible to map an intermediate table through a containing object.
public class Subscriber : IEntity
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
private ChannelList _subscribedList { get; set; }
public int NumSubscribedChannels { get { return _subscribedList.Count(); } }
}
public class HelpChannel : IEntity
{
[Key]
public int Id { get; set; }
public string name { get; set; }
public string category { get; set; }
public int group { get; set; }
}
I need to have a subscriber table, channel table and an intermediate table to link a subscriber to his/her channels.
Is it possible to map the list that is within the ChannelList object to the Subscriber Model?
I figured that's probably not possible and that I would need to just have a private List for EF to map. But I wasn't sure if EF will do that for private variables. Will it?
I'm hoping that is does because if it has to be public to maintain the encapsulation.
You can map private properties in EF code-first. Here is a nice description how to do it. In your case it is about the mapping of Subscriber._subscribedList. What you can't do is this (in the context's override of OnModelCreating):
modelBuilder.Entity<Subscriber>().HasMany(x => x._subscribedList);
It won't compile, because _subscribedList is private.
What you can do is create a nested mapping class in Subscriber:
public class Subscriber : IEntity
{
...
private ICollection<HelpChannel> _subscribedList { get; set; } // ICollection!
public class SubscriberMapper : EntityTypeConfiguration<Subscriber>
{
public SubscriberMapper()
{
HasMany(s => s._subscribedList);
}
}
}
and in OnModelCreating:
modelBuilder.Configurations.Add(new Subscriber.SubscriberMapping());
You may want to make _subscribedList protected virtual, to allow lazy loading. But it is even possible to do eager loading with Include:
context.Subscribers.Include("_subscribedList");

How to set order of appearance for fields when using Html.EditorFor in MVC 2?

I have the following classes in my Model:
public abstract class Entity : IEntity
{
[ScaffoldColumn(false)]
public int Id { get; set; }
[Required,StringLength(500)]
public string Name { get; set; }
}
and
public class Model : SortableEntity
{
[Required]
public ModelType Type { get; set; }
[ListRequired]
public List<Producer> Producers { get; set; }
public List<PrintArea> PrintAreas { get; set; }
public List<Color> Colors { get; set; }
}
To display the "Model" class in the view I simply call Html.EditorFor(model=>model), but the "Name" property of the base class is rendered last, which is not the desired behaviour.
Is it possible to influenece on the order of displayed fields somehow?
I've not been able to find an attribute for that, so your options are:
1) create one, and then revise the base Object.ascx template to account for it, or
2) create a custom editor template for your classes that explicitly put stuff in the order you want.

Categories