need help to map ViewModel to Entity using AutoMapper - automapper

I am new to automapper. need some help to map from ViewModel to Entity.
Here's my user entity
public class User
{
public int Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public DateTime CreatedDate { get; set; }
public string DisplayName { get; set; }
}
here's my ViewModel
public class UserViewModel
{
public string Email { get; set; }
public string Password { get; set; }
}
I create a map. its not working
CreateMap<UserLoginViewModel, User>()
.ForMember(dest=>dest.CreatedDate, DateTime.Now)
.ForMember(dest=>dest.DisplayName, "");
DisplayName and CreatedDate are required fields. since its not in the ViewModel, I will make DisplayName = "" and CreateDate = datetime.now.
I want to know if I can do it using the automapper, or I have to do it after the mapping.
please show me some sample code.

You mentioned that you have UserViewModel view model and User entity however your mapping configuration contains third type - UserLoginViewModel. Supposing that UserLoginViewModel is the same as UserViewModel, you should change you configuration as below.
Mapper.CreateMap<UserViewModel, User>()
.ForMember(dest=>dest.CreatedDate, t=> t.MapFrom(s=> DateTime.Now))
.ForMember(dest=>dest.DisplayName, t=> t.MapFrom(s=> ""));
AutoMapper wiki.

Related

PATCH in ServiceStack

I am trying to patch a object with the following code.
public object Patch(EditBlog request)
{
using (var db = _db.Open())
{
try
{
request.DateUpdated = DateTime.Now;
Db.Update<Blog>(request, x => x.Id == request.Id);
return new BlogResponse { Blog = Blog = Db.Select<Blog>(X=>X.Id == request.Id).SingleOrDefault()};
}
catch (Exception e)
{
return HttpError.Conflict("Something went wrong");
}
}
}
In Postman, I am calling the function like this "api/blog/1?=Title=Test1&Summary=Test&UserId=1".
When debugging I can see that those values has been assigned to the request.
During the Update it throws: "Cannot update identity column 'Id'"
My model looks like this
public class Blog
{
[AutoIncrement]
public int Id { get; set; }
public IUserAuth User { get; set; }
[Required]
public int UserId { get; set; }
[Required]
public string Title { get; set; }
public string Summary { get; set; }
public string CompleteText { get; set; }
[Required]
public DateTime DateAdded { get; set; }
public DateTime DateUpdated { get; set; }
}
And the EditBlog DTO looks like this:
[Route("/api/blog/{id}", "PATCH")]
public class EditBlog : IReturn<BlogResponse>
{
public int Id { get; set; }
public IUserAuth User { get; set; }
public int UserId { get; set; }
public string Title { get; set; }
public string Summary { get; set; }
public string CompleteText { get; set; }
public DateTime DateUpdated { get; set; }
}
The error message "Cannot update identity column 'Id'" does not exist anywhere in ServiceStack.OrmLite, it could be an error returned by the RDBMS when you're trying to update the Primary Key which OrmLite wouldn't do when updating a Model annotated with a Primary Key like your Blog class has with its annotated [AutoIncrement] Id Primary Key.
The error is within your Db.Up<T> method that's performing the update, which is not an OrmLite API, so it's likely your own custom extension method or an alternative library.
I would implement a PATCH Request in OrmLite with something like:
var blog = request.ConvertTo<Blog>();
blog.DateUpdated = DateTime.Now;
Db.UpdateNonDefaults(blog);
i.e. using OrmLite's UpdateNonDefaults API to only update non default fields and updating using the Blog Table POCO not the EditBlog Request DTO.
Also you should use the Single APIs when fetching a single record, e.g:
Blog = Db.SingleById<Blog>(request.Id)
or
Blog = Db.Single<Blog>(x => x.Id == request.Id)
Instead of:
Blog = Db.Select<Blog>(X=>X.Id == request.Id).SingleOrDefault()

EntityFramework : Invalid column name *_ID1

I am trying to implement DbContext for couple of tables called 'Employee' and 'Department'
Relationship between Employee and Department is many to one. i.e. department can have many employees.
Below are the EntityFramework classes I designed ( CodeFirst approach )
[Table("Employee")]
public class Employee
{
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Department_ID")]
public int Department_ID { get; set; }
public virtual Department Department { get; set; }
}
[Table("Department")]
public class Department
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Column("Name")]
public string Name { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
While adding Employee record I am getting below exception
"Invalid column name 'Department_ID1'."
I am not sure why EF is referring to Department_ID1. Do I need to add configuration in OnModelCreating method of DbContext?
I am using EF version 6.1.1
I've also gotten this problem in my EF one-many deals where the one has a List of the many property and my mapping didn't specify that property. For example take:
public class Notification
{
public long ID { get; set; }
public IList<NotificationRecipient> Recipients { get; set; }
}
then
public class NotificationRecipient
{
public long ID { get; set; }
public long NotificationID { get; set; }
public Notification Notification { get; set; }
}
Then in my mapping, the way that caused the Exception (the incorrect way):
builder.HasOne(x => x.Notification).WithMany()
.HasForeignKey(x => x.NotificationID);
What fixed it (the correct way) was specifying the WithMany property:
builder.HasOne(x => x.Notification).WithMany(x => x.Recipients)
.HasForeignKey(x => x.NotificationID);
Hi After spending some time I could fix this problem by using ForeignKey attribute on public virtual Department Department { get; set; } property of Employee class.
Please see below code.
[Table("Employee")]
public class Employee
{
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Department_ID")]
public int Department_ID { get; set; }
[ForeignKey("Department_ID")]
public virtual Department Department { get; set; }
}
This fixed my problem. Are there any other solution to fix this? Using fluent API?
For me, the issue was resolved by removing a (duplicate?) virtual property.
Using the OP's example:
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Department_ID { get; set; }
public virtual Department Department { get; set; }
}
public class Department
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
Turns into:
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Department_ID { get; set; }
}
public class Department
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
In my case I added a virtual property on top of the auto generated property
I fixed it by adding the NotMapped attribute to my property, or you could configure with fluent api
public partial class Control
{
[NotMapped]
public virtual ICollection<Control> Children { get => this.InverseParent; set => this.InverseParent = value; }
}
I had the same error, my issue was the FK was a long but I had it as an int in the model. EF generated a new column because it didn't match types on the FK so it assumed they weren't the same and went ahead with making another one but putting 1 at the end because there was already one with the proper name. Making sure the types matched resolved the issue for me.
This can be fixed simply by putting [NotMapped] annotation on your virtual properties.
public class Employee
{
[ForeignKey("Department")]
public int Department_ID
[NotMapped]
public virtual Department Department { get; set; }
}
And in you modelBuilder:
modelBuilder.Entity<Employee>(entity =>
{
entity.HasOne(e => e.Department);
});
Just flip this around if you want to call by Department.
We use the [NotMapped] annotation so that EF Core will disregard it when looking at your database.

What's the best way to convey required/optional DTO properties in ServiceStack?

I'm having an issue with my ServiceStack w/ Swagger implementation regarding documenting required/optional properties. Developers implementing clients that consume my services love the Swagger documentation, however they don't know which properties are required vs. optional--aside from getting a 400 response on each attempt to get a valid request through.
Take the following example:
public class UserProfile
{
public string FirstName { get; set; }
public string LastName { get; set; }
public UserAddress Address { get; set; }
}
public class UserAddress
{
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 string Country { get; set; }
public string PhoneNumber { get; set; }
}
Swagger will cleanly show both of these types if they are part of my DTO, however I can't convey that FirstName, LastName, or any of the Address properties are required or not. Is there a way to accomplish this without having to roll a separate spec document?
You can use an [ApiMember(IsRequired = false)] attribute on the properties in the DTO to add extra information for swagger ui.
There is list of the attributes that swagger ui will recognise on the servicestack wiki

Deleting child entities in Entity Framework w/ Repository Pattern

I have a child entity:
public class PhoneNumber : KeyedEntityBase
{
public string Number { get; set; }
public string Extension { get; set; }
}
that exists in multiple parents:
public class Customer : KeyedEntityBase
{
public string Name { get; set; }
public PhoneNumber PhoneNumber { get; set; }
}
public class Vendor : KeyedEntityBase
{
public string VendorName { get; set; }
public PhoneNumber PhoneNumber { get; set; }
}
When I want to delete a PhoneNumber from one of the parents I just null it out. Is there a way I can make Entity Framework handle deleting orphan PhoneNumber instances when using a Repository pattern? I believe NHibernate's all-delete-orphan cascade mode does this. Now to do this I have to create a PhoneNumberRepository and explicitly delete the PhoneNumber after I null it out on the parent, and this smells.

AutoMapper - How to map a concrete domain class to an inherited destination DTO class?

I have a flat domain class like this:
public class ProductDomain
{
public int ID { get; set; }
public string Manufacturer { get; set; }
public string Model { get; set; }
public string Description { get; set; }
public string Price { get; set; }
}
I have two DTO classes like this:
public class ProductInfoDTO
{
public int ID { get; set; }
public string Manufacturer { get; set; }
public string Model{ get; set; }
}
public class ProductDTO : ProductInfoDTO
{
public string Description { get; set; }
public string Price { get; set; }
}
Now the problem is:
Scenario #1:
Mapper.CreateMap<ProductDomain, ProductInfoDTO>() // this mapping works fine
Scenario #2:
Mapper.CreateMap<ProductDomain, ProductDTO>() // this mapping is not working and throws System.TypeInitializationException
So my question is how to create mapping between ProductDomain and ProductDTO (which inherits ProductInfoDTO) without breaking the definition of both source and destination classes. Also I dont want to introduce any new inheritance for the domain class ProductDomain.
Thanks
You can build your own custom TypeConverter like this
public class ProductDomainToProductDTOConverter : ITypeConverter<ProductDomain, ProductDTO>
{
public ProductDTO Convert(ProductDomain source)
{
ProductDTO product = new ProductDTO();
product.Price = source.Price;
...
return product;
}
}
And then create a map with your custom TypeConverter like this
Mapper.CreateMap<ProductDomain, ProductDTO>().ConvertUsing<ProductDomainToProductDTOConverter>();

Resources