Automapper - split one class to array of others - automapper

I've got two classes. Values is a source class. How can I use Automapper to create two-elements array of Value classes when StartValA and StartValB should be first instance od Value class and EndValA and EndValB should be the second instance ? Thanks in advance
public class Values
{
public double StartValA { get; set; }
public double StartValB { get; set; }
public double EndValA { get; set; }
public double EndValB { get; set; }
}
public class Value
{
public double ValueA { get; set; }
public double ValueB { get; set; }
}

Related

Autmapper nested mapping

I have the following main class:
public class ResearchOutcome
{
public ResearchOutcomeCategory ResearchOutcomeCategory { get; set; }
public string? UniqueIdentifier { get; set; }
}
And the category class is:
public class ResearchOutcomeCategory
{
public int Id { get; set; }
public string Name { get; set; }
public string? Description { get; set; }
}
The View models for above classes are:
public class ResearchOutcomeDetailVm : IMapFrom<ResearchOutcome>
{
public int Id { get; set; }
public virtual ResearchOutcomeCategoryDetailVm ResearchOutcomeCategory { get; set; }
}
public class ResearchOutcomeCategoryDetailVm : IMapFrom<ResearchOutcomeCategory>
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
Now, I have used the following mapping profile:
// First this one
profile.CreateMap<ResearchOutcomeCategory, ResearchOutcomeCategoryDetailVm>();
profile.CreateMap<ResearchOutcome, ResearchOutcomeDetailVm>();
//Then I tried this one
profile.CreateMap<ResearchOutcome, ResearchOutcomeDetailVm>()
.ForMember(o => o.ResearchOutcomeCategory,
cat => cat.MapFrom( o => o.ResearchOutcomeCategory));
But the ResearchOutcomeCategory is always null. Any help would be appreciated.
After digging more, I identified that I was not "Including" the relevant item in the query, hence, the view model was always empty. Pretty dumb on my part :D
Regarding the mapping, if the properties (even complex ones) have the same names, then the mapper will map them automatically. So simply this line worked
profile.CreateMap<ResearchOutcomeCategory, ResearchOutcomeCategoryDetailVm>();
Hope it helps someone

Servicestack JsConfig with emitLowercaseUnderscoreNames = true does not work on properties with alphanumeric names

I am using Servicestack JsonConfig for serializing and deserializing the JSON. but for the following class, it works for some properties and does not for others.
public class Address
{
public string Street1 { get; set; }
public string Street2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
}
When I deserialize it to JSON ZipCode is correctly represented as "zip_code" but Street1 is represented as "street1" where the expected presentation is "street_1". Following is the code
using (JsConfig.With(emitLowercaseUnderscoreNames: true, propertyConvention: PropertyConvention.Lenient))
{
//serialize into json
requestJsonString = JsonSerializer.SerializeToString(request.SubscriptionRequest);
}
The part of the JSON I am getting is
{"address":{"street1":"100 Tlllbow Street","street2":"100 Taljjow Street","city":"Housthgon","state":"hg","zip_code":"022"}}
Please help. Thanks in Advance.
This behavior is by design, you can change it by providing an alias with [DataMember(Name] attribute, e.g:
[DataContract]
public class Address
{
[DataMember(Name="street_1")]
public string Street1 { get; set; }
[DataMember(Name="street_2")]
public string Street2 { get; set; }
[DataMember]
public string City { get; set; }
[DataMember]
public string State { get; set; }
[DataMember]
public string ZipCode { get; set; }
}
Or by renaming your properties:
public class Address
{
public string Street_1 { get; set; }
public string Street_2 { get; set; }
}

Automapper projection results in empty collection for nested Dto

I have a .Net Core 2 webapi in which I am using automapper to map to Dtos. Everything works fine, except I am seeing an unexpected behaviour when I map an object to a Dto, and where the Dto also contains mappings for a collection. E.g
CreateMap<Order, OrderDto>();
CreateMap<Product, ProductDto>();
Where classes are like this
public partial class Order
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Product> Products{ get; set; }
public int ProductCount {return Products.Count;}
}
public partial class Product
{
public int Id { get; set; }
public int OrderId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
The following works as expected;
The class is mapped, and the ProjectCount is correct in the Dto
public partial class OrderDto
{
public int Id { get; set; }
public virtual ICollection<Product> Products{ get; set; }
public int ProductCount{ get; set; }
}
_context.Orders.Include<>(Products).ProjectTo<>(OrderDto)
But doing the following, the productcount is always zero.
E.g. if I do this;
public partial class OrderDto
{
public int Id { get; set; }
public virtual ICollection<ProductDto> Products{ get; set; }
public int ProductCount{ get; set; }
}
public partial class ProductDto
{
public int Id { get; set; }
public int OrderId { get; set; }
public string Name { get; set; }
}
_context.Orders.Include<>(Products).ProjectTo<>(OrderDto)
Why does this happen, and how can I ensure that it doesnt? This is a real world example where I need a property which references the collection - and I need it in both the base and the Dto. I can do the following which works fine, but it doesnt appear that this should be how it works...
public partial class OrderDto
{
public int Id { get; set; }
public virtual ICollection<ProductDto> Products{ get; set; }
public int ProductCount {return Products.Count;}
}
public partial class ProductDto
{
public int Id { get; set; }
public string Name { get; set; }
}
_context.Orders.Include<>(Products).ProjectTo<>(OrderDto)
I profiled the SQL and found that Automapper changes the way the query is formed. Without the nested projection, two queries are made;
[Queries are more complex than this and use joins, but you get the idea]
Select Id from orders
Select Id,Name from products where productid in [select id from orders ]
With the nested projection, are executed for each nested Dto
Select Id from orders
Select Id,Name from products where id=1
Select Id,Name from products where id=2

How to give a Table name in Entity Framework by code first approach in .Net Framework 4.0?

In .NET 4.0 framework the System.ComponentModel.DataAnnotations.Schema doesn't work or doesn't support I think.
I am using a code-first approach and my database already exists, and also not using ADO.net Entity Data Model.
I already used the [Table] attribute and DatabaseGenerated attribute, it's not working causing a compilation error to occur.
This is my code:
Entity class:
public class myclass
{
public myclass()
{
//
// TODO: Add constructor logic here
//
}
[Key]
public int RECORDID { get; set; }
public string AA { get; set; }
public string CAT { get; set; }
public string CS { get; set; }
public int? FS { get; set; }
public int? CA { get; set; }
public int? DR { get; set; }
public int? UM { get; set; }
public int? ID { get; set; }
public double LAT { get; set; }
public double LON { get; set; }
public int? NIC { get; set; }
}
DbContext class:
public class classContext : DbContext
{
public classContext() : base("name=DBConnection")
{
//Disable initializer
Database.SetInitializer<classContext>(null);
}
public DbSet<myclass> myclasses { get; set; }
}
Or I have to add this override method of model creating, is it helpful or not?
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<myclass>().ToTable("Datatbl");
}
Help me out. Thanks
You can Use Table attribute over your class:
[Table("Datatbl")]
public class myclass
{
}

Mapping from list down to object with AutoMapper

I'm new with AutoMapper and have a problem I'm trying to solve.
If I have a source class like this:
public class Membership
{
public int MembershipId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string OrganizationName { get; set; }
public List<Address> Addresses { get; set; }
}
And the Address class looks like this:
public class Address
{
public int AddressId{ get; set; }
public int RefAddressTypeId { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public bool IsPreferredAddress { get; set; }
}
My destination class is:
public class UserInformationModel
{
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Organization { get; set; }
public string EmailAddress { get; set; }
public PhysicalAddress BillingAddress { get; set; }
public PhysicalAddress ShippingAddress { get; set; }
}
And the destination address class is:
public class PhysicalAddress
{
public AddressType AddressType{get; set;}
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
}
I have set up a mapping like this:
Mapper.CreateMap<MinistryMattersIntegration.BusinessObjects.Entities.Cokesbury.Membership, UserInformationModel>()
.ForMember(dest => dest.Organization, opt => opt.MapFrom(src=>src.OrganizationName));
This is working for Membership to UserInformationModel, but now I need to get addresses working. One important thing to note, though, is that the destination is a single billing address and a single shipping address while in the original model, all the address are stored as a list. The way you find the shipping and billing addresses out of the list is by looking at the RefAddressTypdId and the IsPreferredAddress. Only one preferred address may exist with a particular RefAddressTypeId.
So, my question is, how do you get AutoMapper to do this kind of mapping? Is it possible, or am I better off just going with regular mapping code?
You'll want to use the Custom Value Resolvers feature of AutoMapper. So you'd setup a Custom Resolver to map from your list to your single entity using the IsPreferredAddress flag to find it.
The documentation is pretty good for the Custom Resolvers so you should be fine figuring it out from there.

Resources