c# - Entity Framework 6.自动截断超过DB Field Length的字符串字段
问题描述
首先,为什么要这样做?在生产系统中,如果传入的数据对于数据库来说太大了,如果字段不重要,您可能希望继续运行并接受数据丢失,如果不插入记录,则会出现更大的问题。
我使用以下代码进行了此操作,但是必须反映私有 .net 框架属性,这很丑陋。
当然有更好的方法来做到这一点?我在另一个帖子上看到了以下代码来加载元数据,但它不起作用。以这种方式加载的类型没有填充数据库字段长度。我们从数据库生成模型。这样我们就不必自己手动调整实体模型(数据库优先方法)。
var metaDataWorkspace = ((IObjectContextAdapter)db).ObjectContext.MetadataWorkspace;
var edmTypes = metaDataWorkspace.GetItems<EdmType>(DataSpace.OSpace);
具有逻辑的方法在下面的 AutoTruncateStringToMaxLength() 中。
有以下用途:
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Data.Entity.Core.EntityClient;
using System.Data.Entity.Core.Metadata.Edm;
位于部分实体类(例如公共部分类 MyEntities)中的代码:
public override int SaveChanges()
{
try
{
this.AutoTruncateStringToMaxLength();
return base.SaveChanges();
}
catch (DbEntityValidationException ex)
{
List<string> errorMessages = new List<string>();
foreach (DbEntityValidationResult validationResult in ex.EntityValidationErrors)
{
string entityName = validationResult.Entry.Entity.GetType().Name;
foreach (DbValidationError error in validationResult.ValidationErrors)
{
errorMessages.Add(entityName + "." + error.PropertyName + ": " + error.ErrorMessage);
}
}
// Join the list to a single string.
var fullErrorMessage = string.Join("; ", errorMessages);
// Combine the original exception message with the new one.
var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);
// Throw a new DbEntityValidationException with the improved exception message.
throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
}
}
private void AutoTruncateStringToMaxLength()
{
var entries = this?.ChangeTracker?.Entries();
if (entries == null)
{
return;
}
//********** EDM type from here does not work. MaxLength properties are not set ***************** //
//var metaDataWorkspace = ((IObjectContextAdapter)db).ObjectContext.MetadataWorkspace;
//var edmTypes = metaDataWorkspace.GetItems<EdmType>(DataSpace.OSpace);
ReadOnlyMetadataCollection<EdmMember> memberMetaDataProperties = null;
string currentloadedEdmType = null;
foreach (var entry in entries)
{
var internalEntry = entry.GetType().GetProperty("InternalEntry", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(entry);
var edmType = (EdmType)internalEntry.GetType().GetProperty("EdmEntityType", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).GetValue(internalEntry);
if (edmType != null)
{
if (currentloadedEdmType == null || edmType.Name != currentloadedEdmType)
{
currentloadedEdmType = edmType.Name;
//seems slow to load (in debug) so cache just in case there is performance issue
memberMetaDataProperties = (ReadOnlyMetadataCollection<EdmMember>)edmType.MetadataProperties.FirstOrDefault(x => x.Name == "Members").Value;
}
entry.Entity.GetType().GetProperties().ToList().ForEach(p =>
{
var matchingMemberMetaData = memberMetaDataProperties.FirstOrDefault(x => x.Name == p.Name);
if (matchingMemberMetaData != null && matchingMemberMetaData.BuiltInTypeKind.ToString() == "EdmProperty")
{
var edmProperty = (EdmProperty)matchingMemberMetaData;
if (edmProperty.MaxLength.HasValue && edmProperty.TypeName == "String")
{
string value = (p.GetValue(entry.Entity) ?? "").ToString();
if (value.Length > edmProperty.MaxLength.Value)
{
// oops. Its too Long, so truncate it.
p.SetValue(entry.Entity, value.Substring(value.Length - edmProperty.MaxLength.Value));
}
}
}
});
}
}
}
解决方案
EF Core 有更好的元数据 API。例如
var q = from e in this.Model.GetEntityTypes()
from p in e.GetProperties()
where p.ClrType == typeof(string)
select new { EntityName = e.Name, PropertyName = p.Name, MaxLength = p.GetMaxLength() };
推荐阅读
- angular - 没有收到异步测试用例的 SPEC HAS NO EXPECTATIONS 消息
- javascript - 使用 labels.formatter 在 xAxis 上打印目标标签
- javascript - 如何在javascript中查找文档中存在的元素
- python - Python 请求和 MailJet API 的突然错误
- python - 使用python更改内存中变量的值
- c# - 使“玩家”在阵列中移动的更简单方法
- ruby-on-rails - 调用设计的 sign_in 时返回标头
- java - 声纳:将同步类“Hashtable”替换为非同步类,例如“HashMap”
- xml - 将参数传递给在 Camel 中的 XML 中定义的 RecipientList
- node.js - 使用 nodemon 和 express 优雅关闭