AutoMapper: map entities to a destination with a suffix - automapper

Given the following example:
class Source:
int Id;
DateTimeOffSet StartDate;
DateTimeOffSet EndDate;
...
class Destination:
int Id;
DateTimeOffSet StartDate;
DateTimeOffSet StartDateUtc;
DateTimeOffSet EndDate;
DateTimeOffSet EndDateUtc;
...
How can I map both ways all source properties of type DateTimeOffSet of all my objects from/to their destination properties with the -Utc suffix? (the destination property without the suffix should stay unmapped)

Related

How can I access the RowKey (and PartitionKey) when I use a input binding with a storage Table?

How can I access the RowKey (and PartitionKey) when I use a input binding with a storage Table without the error "hides inherited member 'TableEntity.RowKey"?
I can happily access the categories based on a PartitionKey, but when I try to extend to getting the RowKey, by adding a new property to my class, I get an error ... warning CS0108: 'Person.RowKey' hides inherited member 'TableEntity.RowKey'. Use the new keyword if hiding was intended.
#r "Microsoft.WindowsAzure.Storage"
using Microsoft.WindowsAzure.Storage.Table;
public static void Run(string myQueueItem,
IQueryable<Person> tableBinding, TraceWriter log)
{
log.Info($"C# Queue trigger:triggerblocklist processed message : [{myQueueItem}]");
// int i = tableBinding.Count();
// log.Info($"{i}");
foreach (Person person in tableBinding.Where(p => p.PartitionKey == myQueueItem)
.ToList())
{
log.Info($"RowKey: [{person.RowKey}]");
log.Info($"Categories: [{person.Categories}]");
}
}
public class Person : TableEntity
{
// public string PartitionKey { get; set; }
public string RowKey { get; set; } // !!!!!!!!!!!!!!!!!
// public string Timestamp { get; set; }
public string Categories { get; set; }
}
TableEntity class which you inherit from already has a property called RowKey, so.. your Person class does not need to define a property called RowKey, it already has it through its base class.
All you need to do here is to remove RowKey property from your Person class and no other change is needed.

Creating an Azure Search document schema which enables scoring by filters

My domain objects are like:
public class MainType {
public int Id {get;set;}
public string Name {get;set;}
public List<TypeA> A_List {get;set;}
public List<TypeB> B_List {get;set;}
... other properties
}
public class TypeA {
public int Id {get;set;}
public string Name {get;set;}
... other properties
}
public class TypeAMapping {
public int TypeAId {get;set;}
public int MainTypeId {get;set;}
public int DisplayOrder {get;set;}
}
public class TypeB {
public int Id {get;set;}
public string Name {get;set;}
... other properties
}
public class TypeBMapping {
public int TypeBId {get;set;}
public int MainTypeId {get;set;}
public int DisplayOrder {get;set;}
}
Azure Search index documents does not support for complex types so I need to flatten these all classes into a model as described here.
So, I created a class like this one:
public class MainTypeDocumentModel {
public int Id {get;set;}
public string Name {get;set;}
public List<string> A_Id_List {get;set;}
public List<string> A_Name_List {get;set;}
public List<string> A_DisplayOrder_List {get;set;}
public List<string> B_Id_List {get;set;}
public List<string> B_Name_List {get;set;}
public List<string> B_DisplayOrder_List {get;set;}
... other properties
}
The problem is I also need to process DisplayOrder property of the mapping classes. Which the documentation does not cover.
I can create queries to search MainTypeDocumentModel filtered by A_Id_List and/or B_Id_List. But I need to sort the documents (or score higher) with the values in X_DisplayOrder_List property of the documents.
I checked the Scoring Profile docs from Microsoft but couldn't figure out how to implement for this scenario.
It sounds like what you want is the equivalent of correlated sub-queries on the nested A's and B's. Unfortunately this is not currently possible in Azure Search since it requires built-in support for complex types. This is on our radar but there is no ETA at this time.
In the meantime, you can consider other ways of modeling your domain types as Azure Search indexes. One option is full denormalization; Have an A index and a B index, and repeat Id and Name for each combination with As and Bs. Another option is full normalization; Have separate indexes for MainType, A, B, and the relations between them, and do the "joins" on the client side. There are tradeoffs involved depending on your query patterns and update frequency. This thread on the MSDN forums covers these options in a bit more detail.

Datastax driver exception while instantiating UDT mapper for list of user defined types

I am trying to use Datastax's UDT mapper for a table which contains the list of UDT's. The driver throws an exception while trying to instantiate the UDTmapper. It seems to be unable to map the list of instances of the class which represents my UDT.
The user defined types and tables are created with the statements:
CREATE TYPE IF NOT EXISTS keyspace.value (
id uuid,
values list<text>
);
CREATE TYPE IF NOT EXISTS keyspace.epoch (
name text,
description text,
start_time timestamp,
duration int,
values list<frozen<value>>
);
CREATE TABLE IF NOT EXISTS keyspace.service_level_agreements (
id uuid,
name text,
description text,
epochs list<frozen<epoch>>,
chargeback_info uuid,
PRIMARY KEY (id)
);
The classes are:
public class Value {
#Field(name = "id")
private UUID sloId;
#Field(name = "values")
private List<String> values;
}
public class Epoch {
#Field(name = "name")
private String name;
#Field(name = "description")
private String description;
#Field(name = "start_time")
private Date startTime;
#Field(name = "duration")
private long duration;
#Field(name = "values")
private List<Value> values;
}
#UDT (keyspace = "keyspace", name = "service_level_agreements")
public class ServiceLevelAgreement e {
#Field(name = "id")
private UUID id;
#Field(name = "name")
private String name;
#Field(name = "description")
private String description;
#Field(name = "epochs")
private List<Epoch> epochs;
#Field(name = "chargeback_info")
private UUID charegebackInfo;
}
When I am trying to instantiate UDT mapper I am getting an exception:
Cannot map unknown class com.me.Epoch for field private java.util.List com.me.ServiceLevelAgreement.epochs
It seems that the UDT mapper cannot fund Epoch class although it is on the classpath. I also tried to move Epoch class inside ServiceLevelAgreement , but it did not help. Any Idea what I am doing wrong?
The issue was caused by my misunderstanding what class should be tagged with #UDT annotation. I put it instead of the table annotation, but it should in the class which describes my UDT. After I fixedthe annotations, everything started working.

AutoMapper ignoring IsSourceValueNull when using ForAllMembers

I have the latest 3.1.1 version of AutoMapper. For some reason the IsSourceValueNull when using ForAllMemebers doesn't seem to work or I am expecting a different result:
Here is an example of what I am trying to do. Please refrain from commenting on the DTOs looking exactly like the Entities. This is just an example of what I am running into with a more complex model.
public class User{
public int Id {get;set;}
public string UserName {get;set;}
public virtual int? ContactId {get;set;} //Foreign Key to contact object
public virtual Contact Contact {get;set;}
}
public class Contact {
public int Id {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
}
public class UserDto {
public int Id {get;set;}
public string UserName {get;set;}
public int? ContactId {get;set;} //Foreign Key to contact object
public ContactDto Contact {get;set;}
}
public class ContactDto {
public int Id {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
}
The code for the mapping looks something like this:
AutoMapper.Mapper.CreateMap<User,UserDto>().ForAllMembers(u => u.Condition(s => !s.IsSourceValueNull));
AutoMapper.Mapper.CreateMap<Contact,ContactDto>();
I am getting an error that the Source Value cannot be null. Meaning, the Contact is null coming back from the DB, which is OK, but AutoMapper is not running the condition for the Cotnact or ContactId. Both can be null in the DB. I have had to resort to checking if the source is null inside a ForMember block.

using JAXB, the XML is loaded into a class. This class is then used within another class to be marshalled out differently

Given an XML file of offerings that is then loaded into a class called Offerings via JAXB.
This class has the following:
Name, Price sub-Class, Modifiers, Ordering Rules etc.
I then create an order and within that order
Order
public class ProductOrder {
private String OrderId;
private Date createDate;
private OrderStatus orderStatus;
private int CustomerOrderID;
private ArrayList<ProductOrderItem> productOrderItems = new ArrayList<ProductOrderItem>();
}
Order Item
public class ProductOrderItem {
private int OrderItemID;
private **Offering** offering;
private Map<String, Integer> qtylist = new HashMap<String, Integer>();
private ArrayList<Modifier> modifiers = new ArrayList<Modifier>();
private int qty;
}
Offering
#XmlRootElement(name = "offering")
#XmlAccessorType(XmlAccessType.FIELD) // NONE)
public class Offering {
#XmlAttribute
private String id;
#XmlElement
private String offeringName;
#XmlElement
private String description;
#XmlElement
private Integer price;
}
The Offering and Modifiers are classes with JAXB already which I only want to push part of the XML. How would I change the anotations such that only part of the elements are sent? For example not the offering -> modifiers?
Use #XmlTransient instead of the #XmlElement tag.

Resources