Handling null values when using automapper and the Entity Framework - entity-framework

I'm using automapper to map values from one object to another and then saving the object to a db using ef6. I would like Automapper to ignore any null values in the base so that the EF doesn't overwrite the original stored value with null. I've tried the below code but it seems the properties are set as null as the values are removed when stored in the db.
Any ideas?
cfg.CreateMap<BidBase, ProjectBase>()
.ForMember(dest => dest.RambollProjectStartDate, opt => opt.MapFrom(src => src.ExpectedProjectStartDate))
.ForAllMembers(opt => opt.Condition((source, destination, sourceMember) => sourceMember != null));
Update
I've realised that the problem is because automapper sets the properties of the destination object to null if they do not exist in the source object. This means that the value in the db is being set to null by the EF. How can I handle this?

Try use conditional mapping:
https://github.com/AutoMapper/AutoMapper/wiki/Conditional-mapping
How to configure Conditional Mapping in AutoMapper?

Related

Mapping TPT inheritance in Entity Framework 6 (core)

Consider two tables, table BaseService with PK ID, and table SubService with PK BaseServiceID, which is a foreign key to ID in the BaseService table. I wish to map these to classes in EF6 where SubService inherits from BaseService. I'm not sure how to describe in the mapping that the foreign key is from SubService.BaseServiceID to BaseService.ID. At the moment I have something like this:
modelBuilder.Entity<SubService>(e => {
e.ToTable("SubService");
});
and
modelBuilder.Entity<BaseService>(e => {
e.ToTable("BaseService");
e.HasKey(x => x.ID);
});
When I query though, the resulting query tries to join using BaseService.ID to SubService.ID. I've tried a few variations on my mapping, but I'm getting nowhere - can anyone suggest how this should be done?
From my testing, EF doesn't currently support having different column names for the keys in the tables in a TPT mapping. If you configure one entity to map its "Id" property to a column called "FooId", then all entities in the hierarchy will map their keys to "FooId".
You can create an EF Core Issue to provide feedback on this scenario.
modelBuilder.Entity<SubService>()
.ToTable("SubService")
.HasRequired(s => s.BaseService)
.WithMany(b => b.SubServices)
.HasForeignKey(s => s.BaseServiceID);
In this example, a HasRequired method is used to specify that the entity requires a and the method is used to specify the ability to navigate on the side of the relationship. Finally, `BaseService' property class'SubService' 'BaseService' 'WithMany' 'BaseService' 'HasForeign' 'KeyBase' 'ServiceID' 'SubService'

Entity Framework Core set column to nvarchar(max) with code first

I am using Entity Framework Core 7.0.0 and in my OnModelCreating method I am trying to specify a column to be of type nvarchar(max).
In EF6 (not Core!), we were able to do something like:
modelBuilder.Entity<Log>().Property(p => p.Errors).IsMaxLength();
However, I am not able to figure this out in EF Core. Is there something similar available in EF Core that I am missing?
I know that it would normally default all properties of type string to nvarchar(max) but I am overriding DbContext's ConfigureConventions with the following, to default all string to 50 characters:
configurationBuilder.Properties<string>().HaveMaxLength(50);
With help of [Column] data annotation:
[Column(TypeName = "nvarchar(MAX)")]
With help of Fluent API:
entity.Property(p => p.Errors)
.HasColumnName("YourColumnName")
.HasColumnType("nvarchar(MAX)");
HasColumnName: the HasColumnName attribute is applied to a property to specify the database column that the property should map to when the entity's property name and the database column name differ.
HasColumnType: the HasColumnType method is applied to a property to specify the data type of the column that the property should map to when the type differs from convention.

entity framework InMemoryDatabase context.Entity,Add() exception with incorrect key

In the seeding stage of Integration Tests I am adding "Cottages".
Each Cottage has a CottageId, which is set up in IEntityTypeConfiguration's Configure method as builder.HasKey(x => x.CottageId);
Two entities have different CottageIds but the same CottageCode.
I am a bit baffled as to why I get the exception below on context.Cottages.Add for the second entity, when the key (CottageId) is different for each, and CottageCode is NOT the key:
The instance of entity type 'Cottage' cannot be tracked because
another instance with the key value '{CottageCode: 3728}' is already
being tracked. When attaching existing entities, ensure that only one
entity instance with a given key value is attached.
Is the in-memory db making it's own decision about what is they key? If so how can I correct it?
Inspired by #ivan-stoev I looked a lot harder.
In the configuration for another entity I had
builder.HasOne(x => x.Cottage).WithMany(x => x.CottageAccessRights)
.HasPrincipalKey(x => x.CottageCode)
.HasForeignKey(x => x.CottageCode);
HasPrincipalKey adds a unique constraint on CottageCode.
Reworking the relationship solved the issue.

How do I map a NULL / NOT NULL discriminator value in DbContext Fluent Mappings?

I am converting from an EDMX using ObjectContext to Code First models with Fluent Mappings.
In my model I have a TPH inheritance mapping where is the value of the Discriminator field is NULL it is one type, and NOT NULL it is the other type. This mapping is valid and works in the EF designer. Here is the inheritance mapping:
this.Map<TemplateSnapin>(m =>
{
m.Requires("TemplateId").HasValue(Guid.Empty); <<-------
});
this.Map<UserSnapin>(m =>
{
m.Requires("TemplateId").HasValue(null);
});
I don't know what to put where the arrow is above. I just put Guid.Empty to get my project to compile for now so I can continue working.
What is the correct syntax for this Fluent API mapping?

Why does the `DatabaseGeneratedOption.None` exist?

This is used with the Property(() => p).HasDatabaseGeneratedOption() call. Is is perhaps to turn off default DB value generation?
EF uses DatabaseGeneratedOption to figure out what to do with the value of a key column for new entities. If the DatabaseGeneratedOption is Identity EF knows that the value the property is set to can be ignored and that the one that comes from the database should be used. If the DatabaseGeneratedOption is None EF will insert the value of the property to the database as the value of the key column.
In Code First - when Code First conventions find an int property that can be the key property for the given entity they by default will configure this column as identity column (meaning the database will generate the value of the key column/property). DatabaseGeneratedOption.None allows you to overwrite this if you want to set key values on your own.
Its effect is to configure EF to not fetch a new identity value after inserting into the database.