Below is the sample code
public People{
public int Age{get;set;}
public string Name{get;set;}
public string Address{get;set;}
}
public PeopleDto{
public int Age{get;set;}
public string Name{get;set;}
public string Address{get;set;}
}
Now, I want to map the Age and Name fields, while the Address field keeps the default value,I would like to have a function like the following available:
var config= TypeAdapterConfig.GlobalSettings.Default.Config.Clone();
config
.ForType<People, PeopleDto>()
.IncludeFields(src=>src.Age,src=>src.Name)//This method does not currently exist, here is just an example
.MaxDepth(2);
Can this be done please?
I searched for relevant information but did not find any usable information.
it's fixed
var config= TypeAdapterConfig.GlobalSettings.Default.Config.Clone();
config
.ForType<People, PeopleDto>()
.IgnoreMember((m, s) => s == MemberSide.Source)
.Map(d => d.Name, s => s.Name)
.Map(d => d.Age, s => s.Age);
Related
I have an interface like what u see below and I want it to return me a Property Called "ProductionCostId" which has a type of 'int' from a table in the database
int Get(Guid productionLineId, string productionCode)
In the implementation as you can see I want to get this value from a child entity called "ProductionAssignmetnt"
public int Get(Guid productionLineId, string productionCode)
{
return GetAll()
.Where(x => x.ProductionAssignments
.Where(x => x.ProductionLine.Id == productionLineId && x.ProductionCode == productionCode)
.Select(x => x.ProductionCostId);
}
But I dont know how to get this int value
First, you need to include the productionassignments table to this query i.e. join it.
In your GetAll() method where you return in you can join a table using code first by _context.ProductionLines.Include(x => x.ProductionAssignments), if you're on Database First then read this on how to join tables
Now since you haven't posted any model, this is how you'd select if your ProductionCostId is nested inside the assignments
GetAll()
.FirstOrDefault(pLine => pLine.Id == productionLineId)
?.ProductionAssignments.FirstOrDefault(assignment => assignment.ProductionCode == productionCode)?.ProductionCostId)
This query will get the production line with the id, and then select the first productionCostId from the assignments where the code matches. This query assumes the Model
public class ProductionLine
{
public int Id {get;set;}
public List<ProductionAssignment> ProductionAssignments {get;set;}
}
public class ProductionAssignment
{
public int ProductionCode {get;set;}
public int ProductionCostID {get;set;}
public ProductionLine ProductionLine {get;set;}
}
Beware of null reference exceptions.
Is there any better way to Write UDTMaps is the same way as Tables using Cassandra Database with C# Driver
Suppose there is a Table called Users(Id, name text, Address frozen )in Cassandra Database.
now to map this to C#
for Tables I can write as below
public class AppMappings : Mappings
{
public AppMappings()
{
For<User>()
.TableName("Users")
.Column(u => u.Id, cm => cm.WithName("userId"))
.Column(u => u.Name, cm => cm.WithName("username"))
.Column(u => u.AddressDetails , cm => cm.WithName("address"))
.PartitionKey(u=> u.Id);
}
}
public class User
{
public Guid Id {get;set;}
public string Name {get;set;}
public Address AddressDetails {get;set;}
}
public class Address {
public string State {get;set;}
public string City {get;set;}
}
Now I can Apply any Configurations with Single Class AppMappings , it can have many mappings with tables. With this one line I can initialize all mappings
MappingConfiguration.Global.Define<AppMappings>();
but inroder to apply UDT I need to add the below line manually.
session.UserDefinedTypes.Define(UdtMap.For<Address>("address_udt"));
Assume I have 10/20 UDTs then I need to add this line for every UDT. instead is there any way to add UDT Mappings in one place like Mappings?
or better approach to add UDT Mappings ?
Unfortunately the driver doesn't have an utility like that one for UDT mappings but you can create something similar like this:
public abstract class CustomUdtMappings
{
private readonly IDictionary<Type, UdtMap> _definitions = new Dictionary<Type, UdtMap>();
public UdtMap[] Definitions => _definitions.Values.ToArray();
public UdtMap<TPoco> For<TPoco>(string udtName = null, string keyspace = null) where TPoco : new()
{
if (_definitions.TryGetValue(typeof(TPoco), out var map) == false)
{
map = UdtMap.For<TPoco>(udtName, keyspace);
_definitions.Add(typeof(TPoco), map);
}
return (UdtMap<TPoco>) map;
}
}
Then create your mappings class that contains the udt mappings:
public class MyAppUdtMappings : CustomUdtMappings
{
public MyAppUdtMappings()
{
For<Udt1>("udt1")
.Map(udt => udt.Id, "iid")
.Map(udt => udt.Column1, "aasd");
For<Udt2>("udt2")
.Map(udt => udt.Id, "iiid")
.Map(udt => udt.Column1, "aaasd");
}
}
And you can use it this way:
await session.UserDefinedTypes.DefineAsync(new MyAppUdtMappings().Definitions).ConfigureAwait(false);
I think it makes a lot of sense to add something like this to the driver so I created https://datastax-oss.atlassian.net/browse/CSHARP-897 to track this.
I have a model which has a generic properties property looking something like this:
public class GenericProperty
{
public string Name { get; set; }
public object Value { get; set; }
}
Next to that I have a object that has a list with GenericProperties like this:
public class GenericEntity
{
public string Name { get; set; }
public List<GenericProperty> Properties { get; set; }
}
Now im calling a API that deserialize the json to the model above. Next i want to use AutoMapper to construct an actual good looking model so i did the following:
Mapper.Initialize(x =>
{
x.CreateMap<GenericEntity, MyModel>()
.ForMember(d => d.ManagerId, o => o.MapFrom(s => s.Properties.Where(n => n.Name == "ManagerId" ).Select(v => v.Value)))
});
Problem is that this returns the property type and not the actual value:
System.Linq.Enumerable+WhereListIterator`1[MyProject.Models.GenericProperty]
How can i lookup the value of within the model?
By using Where you are selecting all the properties with the name ManagerId. You should instead use Single like in this unit test:
public class TestClass
{
[Test]
public void TestMapper()
{
Mapper.Initialize(x =>
{
x.CreateMap<GenericEntity, MyModel>()
.ForMember(d => d.ManagerId,
o => o.MapFrom(s => s.Properties.Single(n => n.Name == "ManagerId").Value));
});
var ge = new GenericEntity
{
Properties = new List<GenericProperty>
{
new GenericProperty {Name = "ManagerId", Value = "Great"}
}
};
var myModel = Mapper.Map<MyModel>(ge);
Assert.AreEqual("Great", myModel.ManagerId);
}
}
If you can not guarantee that there will be a property with the name ManagerId, you should use SingleOrDefault, and handle the null case.
IMHO, you should limit this kind of AutoMapper configurations to simple cases, since it quickly gets difficult to debug and maintain.
For more complex mappings like this one, I would recommend you to make an explicit mapping method instead, which you can call like an extension method. Another option worth considering if you want to use Automapper are Custom value resolvers.
I am using Dto for data transfer view to domain and use automapper for mapping.
My problem is, the property that not exist dto but i need to set before mapping to domain.
I have tried to use Linq query to get external data from db on before and after mapping methods but linq query giving error.
Sample below
FooDto
public class FooDto
{
public int MyProperty1 {get;set;}
}
FooDomain
public class Foo
{
public int MyProperty1 {get;set;}
public int MyProperty2 {get;set;}
public int Foo2ID {get;set;}
public virtual Foo2 Foo2 {get;set;}
}
Foo2Domain
public class Foo2
{
public int ID {get;set;}
public int MyProperty1 {get;set;}
}
**AutoMapper*
Mapper.Initialize(x =>
{
x.CreateMap<FooDto, Foo>().BeforeMap(
(src, dest) =>dest.MyProperty2 = dest.Foo2.MyProperty1);
}
I want to set Foo2.MyProperty1 to Foo.MyProperty2 using mapping.
This answer might need to be edited if my assumptions are wrong. The assumption I am making is that the source object has the right data. Based on your sample it looks like your source object's MyProperty2 can be set in the destination object so do map this all you would need to do is:
Mapper.Initialize(x =>
{
x.CreateMap<FooDto, Foo>()
.ForMember(dest => dest.MyProperty2, opt => opt.MapFrom(src => src.MyProperty1))
.ForMember(dest => dest.Foo2.MyProperty1, opt => opt.MapFrom(src => src.MyProperty1));
}
What this code does is it tells AutoMapper when I give you an object of Type FooDto and I am requesting an object of Type Foo. For the destination objects property 'Foo2.MyProperty1' and 'MyProperty2', use the options method MapFrom. Go to the source Object get the MyProperty1 and assign it's value to my destination objects MyProperty2 and Foo2.MyProperty1.
I think this would fix you up.
Right sorry I corrected the answer
I have 2 classes and want to configure mapping from one to another
public class Customer
{
public long CustomerId{get;set;}
public string ShippingAddres{get;set;}
public string BillingAddress{get;set;}
public DateTime DateOfBirth {get;set;}
}
public class Item2
{
public long customer_id{get;set;}
public string shipping_addres{get;set;}
public string billing_address{get;set;}
public DateTime date_of_birth {get;set;}
}
I tried to search the answer but all answers that I find tell to map fields manually:
.ForMember(dest => dest.CustomerId, opt => opt.MapFrom(src => src.customer_id));
I don't want to map each property manually, since I have a lot of properties. I want to configure some rule:
to split property name by '_' and join strings to CamelCase
or in pseudo code:
cfg.AddConditionalObjectMapper().Where((source, destination) => s.Name.Replace("(_)([a-z])","\U1") == d.Name );
The question is not about the Regex, I need to know how to configure such rules in Auto-mapper?
I found a way to configure it, but this method is not universal:
cfg.AddMemberConfiguration().AddName< ReplaceName >( _ => _.AddReplace( "_", "" ) );
cfg.AddMemberConfiguration().AddName< CaseInsensitiveName >();