AutoMapper with Array and JsonApiSerializer.JsonApi.Relationship - arrays

I have an AppService solution with the following Classes and i want to map from the SourceObject to the DestinationObject
Source Classes
public class SourceObject
{
public string Id { get; set; }
public string Name { get; set; }
public JsonApiSerializer.JsonApi.Relationship<SourceChildObject[]> childObjects { get; set; }
}
public class SourceChildObject
{
public string Id { get; set; }
public string type { get; set; }
}
Destination Classes
public class DestinationObject
{
public string Id { get; set; }
public string Name { get; set; }
public JsonApiSerializer.JsonApi.Relationship<DestinationChildObject[]> childObjects { get; set; }
}
public class DestinationChildObject
{
public string Id { get; set; }
public string type { get; set; }
}
Auto mapper is setup in the sartup class
services.AddAutoMapper(typeof(EntityMappingProfile));
And my mapping class loos like this
public class EntityMappingProfile : Profile
{
public EntityMappingProfile()
{
CreateMap<SourceObject, DestinationObject>();
CreateMap<Relationship<SourceChildObject[]>, Relationship<DestinationChildObject[]>>();
}
}
When i execute the solution all fields are mapped apart form the array field of type JsonApiSerializer.JsonApi.Relationship. The destination field is null. What am i doing wrong?

You forgot about creating a map between SourceChildObject and DestinationChildObject. Add this line to your EntityMappingProfile.
CreateMap<SourceChildObject, DestinationChildObject>();
And one more thing, when you are mapping generic types, you can enable mapping for all types with:
CreateMap(typeof(Relationship<>), typeof(Relationship<>));
instead of creating a map with concrete use case of a generic type.

Related

Entity Framework Core - How to include/populate a navigation property with custom(1-to-1) query in EF?

How to include/populate a navigation property with custom(1-to-1) query in EF?
e.g.
public class Item {
public int Id { get; set; }
public string Name { get; set; }
[ForeignKey("Id")]
public ItemCost LatestCost {get; set; }
}
public class ItemCost {
public int Id { get; set; }
public DateTime From { get; set; }
public DateTime? To { get; set; }
public decimal Cost { get; set; }
}
Goal is to populate the LatestCost property of the Item with it's latest cost from ItemCosts. How is this being accomplished with EF or what's your take on this?
Is it possible to do a custom query within .Include/.ThenInclude methods?
e.g.
.ThenInclude(a => { a.LatestCost = (from a _db.ItemCosts
where... select a).SingleOrDefault() })...
You could use a virtual get-only property. Your nav property should really be an ICollection<ItemCost>. In this example I'm assuming the Id property in the ItemCost class is the id of the related Item, but it's not clear. Tip: using nameof(property) instead of hard-coding the property name will allow the compiler to catch errors with the name if you were to change it for some reason. The [NotMapped] attribute tells Entity Framework to not try and map the property to a database field.
public class Item {
public int Id { get; set; }
public string Name { get; set; }
public ICollection<ItemCost> ItemCosts {get; set; }
[NotMapped]
public virtual ItemCost LatestCost
{
get
{
return ItemCosts.OrderByDescending(x => x.From).FirstOrDefault();
}
}
}
public class ItemCost {
public int Id { get; set; }
public DateTime From { get; set; }
public DateTime? To { get; set; }
public decimal Cost { get; set; }
[ForeignKey(nameof(Id))]
public virtual Item Item { get; set; }
}

How to to make entity relationships in WEB API database?

I'm making a task management tool using AngularJS for the frontend and ASP.NET WEB API 2 for the backend. I have two entities in the database, a "Task" and a "Type". Each task has one type associated. The user fills a form when he can create a new task, and he has to select a type for that task.
Here's the C# code:
// KBTM_Task.cs file
public class KBTM_Task
{
public int ID { get; set; }
public string TaskID { get; set; } // User defined ID
public string Title { get; set; }
public string Description { get; set; }
}
// KBTM_Type.cs file
public class KBTM_Type
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
So my question is: how do I "connect" the two in the database? What I mean is, let's say I want to POST data to the database. I have to make two POSTs, right? One for the Task and one for the Type, since they're two separate entities.
But since they're stored with two different IDs, how do I know that a certain task has a certain type? In other words, if I send a GET request to KBTM_Task, how do I get the type of that task?
Modify your KBTM_Task entity to include the Type Id and foreign key relationship
public class KBTM_Task
{
public int ID { get; set; }
public string TaskID { get; set; } // User defined ID
public string Title { get; set; }
public string Description { get; set; }
public int TypeID { get; set; }
[ForeignKey("TypeID")]
public virtual KBTM_Type Type { get; set; }
}
This way when you get the data from the API your task object will already include the key ("TypeID") that can be updated and related object ("Type") that you can access its properties (Name, Description, ...).
When you update TypeID on the client object (model) you can simply push the updated task object to the API using $http.put() to handle the database update.
1) Add foreign key using fluent api (or data annotation)
// KBTM_Task.cs file
public class KBTM_Task
{
public int ID { get; set; }
public string TaskID { get; set; } // User defined ID
public string Title { get; set; }
public string Description { get; set; }
public int KBTM_TypeID {get;set}
public virtual KBTM_Type {get; set}
}
// KBTM_Type.cs file
public class KBTM_Type
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public KBTM_Task KBTM_Task { get; set;}
}
Add the following in the class inheriting from DbContext
public class KbtmContext : DbContext
{
...
//public virtual DbSet<KBTM_Task> KbtmTasks {get; set;}
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure KBTM_TypeID as FK for KBTM_Task
modelBuilder.Entity<KBTM_Task>()
.HasRequired(k => k.KBTM_Type)
.WithRequiredPrincipal(ad => ad.KBTM_Task);
}
}
2) If exposing the entity class in API response or request then you need to exclude navigation property from being serialized.
// KBTM_Task.cs file
public class KBTM_Task
{
...
[JsonIgnore]
public virtual KBTM_Type Type { get; set; }
}
To use the [JsonIgnore] atttribute use Install-Package Newtonsoft.Json in package manager console.(One of the popular solutions to manage serialization)

Serialize complex properties with Dapper

Is it possible to make Dapper.NET serialize complex properties with Json.NET? The object should be serialized and then stored into a column as string:
public class Person
{
public string Id { get; set; }
public Address Address { get; set; } // store this as string in database
...
}
public class Address
{
public string City { get; set; }
public string ZipCode { get; set; }
}
Right now we do this manually using ADO.NET:
command.Parameters.AddWithValue("#Id", obj.Id);
command.Parameters.AddWithValue("#Address", obj.Address != null ? JsonConvert.Serialize(obj.Address) : (object) DBNull.Value);
...

Asp.net mvc using EntityFramework: loading Person by passing id is retrieving a Object but Object properties are null?

i am hanging for while and i dont understand one thing...I will try to explain my issue...
I have model(Table) called FeuerwehrPerson and the class looks like that:
public partial class FeuerwehrPerson
{
public FeuerwehrPerson()
{
this.BuchungenResultateList = new List<BuchungenResultate>();
this.Notenspiegel=new Notenspiegel();
this.Gemeinde=new Gemeinde();
}
public int FeuerwehrPersonId { get; set; }
public string Anrede { get; set; }
public string Vorname { get; set; }
public string Nachname { get; set; }
public System.DateTime Geburtstag { get; set; }
public string Strasse { get; set; }
public string Plz { get; set; }
public string Ort { get; set; }
public string Telefon { get; set; }
public int GemeindeId { get; set; }
public Nullable<int> NotenspielgelId { get; set; }
public virtual ICollection<BuchungenResultate> BuchungenResultateList { get; set; }
public virtual Gemeinde Gemeinde { get; set; }
public virtual Notenspiegel Notenspiegel { get; set; }
}
In Feuerwehrperson are 2 Foreign Keys
GemeindeId
NotenspiegelId
and both of them are holding some values for a specific FeuerwehrPerson.
Both Foreign Keys are not null in my FeuerehrPerson Table...
In my Controller i have a Edit Action...and i am searching for FeuerwehrPerson by id...thats working fine:
FeuerwehrPerson feuerwehrperson = db.FeuerwehrPerson.Find(id);
When i am checking the values by using add Watch of feuerwehrperson Object there are some empty properties which shouldn´t be empty
The Object property Gemeinde should contain some values but its empty...also for Notenspiegel Object should contain SeminarA=true, SeminarB=true, SeminarC=true, rest is false but everything is false also NotenspiegelId and GemeindeId...but the Foreign Key references in Feuerwehrperson are not null...but why is it empty????
Please help me...

How could I pass a Generic List from Client to Server in WCF?

I query data with NHibernate in the server side, then I create a WCF service which is the one that publishes these NHibernate objects, they are correctly serialized to Silverlight, I modify them in my application but when I send them back to the server they get serlialized again, and Generic Lists get converted to Array so I cannot modify them anymore in the server side...
this is my class definition
public class BIMenu
{
public virtual Guid ID { get; set; }
public virtual String DisplayName { get; set; }
public virtual String ProgramToCall { get; set; }
public virtual IList<BIMenu> Children { get; set; }
public virtual IList<BISecurityProfile> SecurityProfiles { get; set; }
public virtual Boolean IsApplication
{
get
{
if (Children.Count < 1 && ProgramToCall != null)
return true;
return false;
}
}
public virtual Boolean IsFolder
{
get
{
return !IsApplication;
}
}
public BIMenu()
{
Children = new List<BIMenu>();
SecurityProfiles = new List<BISecurityProfile>();
}
}
and this is my contract
[ServiceContract]
public interface IBISecurityService
{
[OperationContract]
BIMenu GetMenu(String Name);
[OperationContract]
void SaveMenu(BIOnline.Model.BIMenu Menu);
[OperationContract]
void DeleteMenu(BIOnline.Model.BIMenu Menu);
}
Is your BIMenu class marked [DataContract]? I would expect it to be:
[DataContract]
public class BIMenu
{
[DataMember]
public virtual Guid ID { get; set; }
[DataMember]
public virtual String DisplayName { get; set; }
[DataMember]
public virtual String ProgramToCall { get; set; }
[DataMember]
public virtual IList<BIMenu> Children { get; set; }
[DataMember]
public virtual IList<BISecurityProfile> SecurityProfiles { get; set; }
Also, if your IList<BIMenu> Children and IList<BISecurityProfile> SecurityProfiles properties are being set to instances of the Array type, then that is perfectly valid, since Array implements IList. If you want to keep them as actual List<> instances, then just define the properties as List<> instead of IList<>, like this:
// Defined as actual Lists, not IList interfaces.
[DataMember]
public virtual List<BIMenu> Children { get; set; }
[DataMember]
public virtual List<BISecurityProfile> SecurityProfiles { get; set; }

Resources