
Entity framework core truncating strings based on Length Constraint
Have you ever tried to insert some data and you run into errors saying that can’t insert value because it would be truncated. This is entity frameworks way of telling that your value has more characters then the database is configured to accept.
In Entity framework core do do this automatically by using Value Conversions. They are set during the configuration of your model builder and are very helpful if you want to do get full control of the values going in and out.
Here is an example of that in action. We have an entity named TestEntity and we use Value Conversion to trim the string coming in and out. Using conversion will solve many problems with manipulating data going in and out.
modelBuilder.Entity<TestEntity>(entity =>
{
entity.Property(e => e.Name)
.HasColumnName("Name")
.HasMaxLength(20)
.HasConversion(v=>v.Trim(),v=>v.Trim());
});
Another scenario where you might run into would be having to truncate all strings to their max length before saving them to the database. And if you have to do this for lots of properties doing it manually would become time consuming and changing the database model would require you to change you truncating code as well.
Below we will look into doing this for the entire entity framework graph in a few lines of code.
Lets start by creating an extension called TruncateStringForChangedEntities
public static class EfExtensions
{
public static void TruncateStringForChangedEntities(this DbContext context)
{
}
}
First things first. We need to get a list of properties that are strings and have length limitations, we don’t need to concern ourselves with the ones that don’t, they already are at their max value so they won’t be a problem.
public static class EfExtensions
{
public static void TruncateStringForChangedEntities(this DbContext context)
{
var stringPropertiesWithLenghtLimitations = context.Model.GetEntityTypes()
.SelectMany(t => t.GetProperties())
.Where(p => p.ClrType == typeof(string))
.Select(z => new
{
StringLength = z.GetMaxLength(),
ParentName = z.DeclaringEntityType.Name,
PropertyName = z.Name
})
.Where(d => d.StringLength.HasValue);
}
}
The above code, finds all properties that are strings and they have the StringLength constraint set.
Now that we have the properties we need to get all the changed objects on the graph. Changed objects are in the sate of Added or Edited.
public static class EfExtensions
{
public static void TruncateStringForChangedEntities(this DbContext context)
{
var stringPropertiesWithLenghtLimitations = context.Model.GetEntityTypes()
.SelectMany(t => t.GetProperties())
.Where(p => p.ClrType == typeof(string))
.Select(z => new
{
StringLength = z.GetMaxLength(),
ParentName = z.DeclaringEntityType.Name,
PropertyName = z.Name
})
.Where(d => d.StringLength.HasValue);
var editedEntitiesInTheDbContextGraph = context.ChangeTracker.Entries()
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
.Select(x => x.Entity);
}
}
We use the ChangeTracker and get entries from it. Then we filter those entries by state which match Added or Modified.
Once we have the properties and the edited objects now we an go through each edited object and modify the properties to truncate the strings.
public static class EfExtensions
{
public static void TruncateStringForChangedEntities(this DbContext context)
{
var stringPropertiesWithLenghtLimitations = context.Model.GetEntityTypes()
.SelectMany(t => t.GetProperties())
.Where(p => p.ClrType == typeof(string))
.Select(z => new
{
StringLength = z.GetMaxLength(),
ParentName = z.DeclaringEntityType.Name,
PropertyName = z.Name
})
.Where(d => d.StringLength.HasValue);
var editedEntitiesInTheDbContextGraph = context.ChangeTracker.Entries()
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
.Select(x => x.Entity);
foreach (var entity in editedEntitiesInTheDbContextGraph)
{
var entityFields = stringPropertiesWithLenghtLimitations.Where(d => d.ParentName == entity.GetType().FullName);
foreach (var property in entityFields)
{
var prop = entity.GetType().GetProperty(property.PropertyName);
if (prop == null) continue;
var originalValue = prop.GetValue(entity) as string;
if (originalValue == null) continue;
if (originalValue.Length > property.StringLength)
{
prop.SetValue(entity, originalValue.Substring(0, property.StringLength.Value));
}
}
}
}
}
For every edited object, we get the fields that belong to that object and for every field we truncate the string if it needs truncating.
This function needs to be called just before the SaveChanges().
Since we made it an extension method it can be used with all your DbContexts
var myDbContext = new MyDbContext();
//add edit your entities
myDbContext.TruncateStringForChangedEntities();
myDbContext.SaveChanges();
That’s it now all the objects that have been added or edited, we go through their properties and see if their properties have string length and truncate it to that value.
This can be really helpful in scenarios where you are accepting data without validating it and don’t want to thogh an error if that data is longer that it should be but just truncate it

Logging inside your nuget packages
Error logging for nuget packages with support to be configured from the consumer using the options builder pattern to allow the consumer full power over the configuration process

A different way of patching for your api
If you ever tried to implement patching for your api, you imeditely run into confusion and lots of things that need to be considered come up. Things like validation, what if i need some properties to be always present, what messages should i send back to the caller. How to map all the patch properties to my model etc.

C# word template parser
In this article we talk about parsing a word template and replacing variables.

Converting excel to json using C#.
Excel to json in just a couple of lines using c# and .net standard, so you can run it in any platform