回答
我居然找到一個更好的辦法這實際上是在系統中構建的,再加上它使用實體的內部序數元數據(我沒有測試性能差異,但這應該比反射快得多):
private const string StringType = "String";
private const EntityState SavingState = EntityState.Added | EntityState.Modified;
public override int SaveChanges()
{
//when using on ObjectContext replace 'objectContext' with 'this',
//and override SaveChanges(SaveOptions options) instead:
var objectContext = ((IObjectContextAdapter)this).ObjectContext;
var savingEntries = objectContext.ObjectStateManager
.GetObjectStateEntries(SavingState);
foreach (var entry in savingEntries)
{
var curValues = entry.CurrentValues;
var fieldMetadata = curValues.DataRecordInfo.FieldMetadata;
var stringFields = fieldMetadata
.Where(f => f.FieldType.TypeUsage.EdmType.Name == StringType);
foreach (var stringField in stringFields)
{
var ordinal = stringField.Ordinal;
var curValue = curValues[ordinal] as string;
if (curValue != null && curValue.All(char.IsWhiteSpace))
curValues.SetValue(ordinal, null);
}
}
return base.SaveChanges(); //SaveChanges(options) on ObjectContext
}
不是我所知道的。
你可能編寫從ObjectContext
繼承一個類並重寫SaveChanges()
做到這一點,用它來代替你的x.objectlayer.cs/x.designer.cs ObjectContext
哎呀,雖然即時編寫這個你發佈它...大聲笑 謝謝,我投了 – Shimmy 2009-07-13 14:22:39
如果你使用Entity Framework 4,你可以使用T4模板來完成留下這個。只要將它放在.tt模板文件中每個字符串屬性的getter中,它就會用null替換空字符串並自動修剪字符串。無需使用反射。
<#+ if (primitiveProperty.TypeUsage.ToString().Split('.').Last() == "String") { #>
if (value == "") value = null;
else value = value.Trim();
<#+ } #>
我們使用反向POCO生成器,我實際上需要相反(將空字符串轉換爲空)。你知道你的建議是否適用於這種情況? – Naomi 2014-09-29 15:34:06
我剛剛調整了上面的代碼到新版本的實體框架4.1(DbContext)。
public override int SaveChanges()
{
var objContext = ((IObjectContextAdapter)this).ObjectContext;
var entries = objContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified).Select(
entry => entry.Entity);
foreach (var entity in entries)
{
string str = typeof(string).Name;
var properties = from p in entity.GetType().GetProperties()
where p.PropertyType.Name == str
select p;
foreach (var item in properties)
{
string value = (string)item.GetValue(entity, null);
if (value != null && value.Trim().Length == 0)
{
item.SetValue(entity, null, null);
}
}
}
return base.SaveChanges();
而不是通過重寫的ObjectContext複雜的東西我用字符串擴展方法值轉換爲數據庫存儲
public static class StringExtensions
{
public static string EmptyStringToNull(this string s)
{
return string.IsNullOrWhiteSpace(s) ? null : s;
}
public static object EmptyStringToDBNull(this string s)
{
if (string.IsNullOrWhiteSpace(s))
return DBNull.Value;
else
return s;
}
}
只是爲了完整性,這裏寫成的部分類,而不是繼承接受的答案。請注意,此版本還修剪字符串。
using System.Data;
using System.Data.Objects;
using System.Linq;
public partial class MyObjectContext {
private const string StringType = "String";
private const EntityState SavingState = EntityState.Added | EntityState.Modified;
public override int SaveChanges(SaveOptions options) {
var savingEntries = this.ObjectStateManager.GetObjectStateEntries(SavingState);
foreach (var entry in savingEntries) {
var curValues = entry.CurrentValues;
var fieldMetadata = curValues.DataRecordInfo.FieldMetadata;
var stringFields = fieldMetadata.Where(f => f.FieldType.TypeUsage
.EdmType.Name == StringType);
foreach (var stringField in stringFields) {
var ordinal = stringField.Ordinal;
var curValue = curValues[ordinal] as string;
if (curValue != null && curValue.All(char.IsWhiteSpace)) {
curValues.SetValue(ordinal, null);
}
else if (curValue != null && curValue != curValue.Trim()) {
curValues.SetValue(ordinal, curValue.Trim());
}
}
}
return base.SaveChanges(options);
}
}
我還展示了所需的usings
,因爲我發現它令人沮喪,當我copy'n'paste代碼和IDE拋出了有關類型或命名空間不是發現了一些錯誤。
我用Shimmy's solution,很高興,直到我發現我的複雜類型中的字符串被遺漏。換句話說,我需要一種方法來清除不可空白的字符串,不僅在我的核心對象/記錄中,而且還包括它的任何非原始對象屬性,以及它們的屬性...
以下是我的遞歸適應。我不能說它的優雅和生產質量,因爲它沒有長時間的生活,但它似乎對我來說至今還在工作,並且至少可以作爲其他人的起點。
using System.Data.Entity;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using System.Linq;
public class MyDataContext : DbContext
{
public override int SaveChanges()
{
ObjectStateEntry[] savingObjectStateEntries = ((IObjectContextAdapter)this)
.ObjectContext.ObjectStateManager
.GetObjectStateEntries(EntityState.Added | EntityState.Modified).ToArray();
foreach (ObjectStateEntry savingObjectStateEntry in savingObjectStateEntries)
SetEmptyStringsToNull(savingObjectStateEntry.CurrentValues);
return base.SaveChanges();
}
private static void SetEmptyStringsToNull(CurrentValueRecord currentValueRecord)
{
if (currentValueRecord != null)
for (int i = 0; i < currentValueRecord.FieldCount; i++)
if (currentValueRecord[i] is CurrentValueRecord)
SetEmptyStringsToNull(currentValueRecord[i] as CurrentValueRecord);
else if ((currentValueRecord[i] is string)
&& (currentValueRecord.DataRecordInfo.FieldMetadata[i].FieldType as EdmProperty).Nullable
&& string.IsNullOrWhiteSpace(currentValueRecord[i] as string))
currentValueRecord.SetValue(i, null);
}
}
這裏是一個實體框架核心(V2測試)的解決方案。由於文檔有限,不得不通過API來實現我的方式,所以可能有其他方法來完成相同的事情。請注意,使用此方法修改原始對象。
public override int SaveChanges()
{
ConvertWhitespaceToNulls();
return base.SaveChanges();
}
private void ConvertWhitespaceToNulls()
{
var entityEntries = this.ChangeTracker
.Entries()
.Where(x => x.State == EntityState.Modified || x.State == EntityState.Added && x.Entity != null);
foreach (var e in entityEntries)
foreach (var currentValue in e.CurrentValues.Properties.Where(p => p.ClrType == typeof(string) && p.IsNullable))
if (string.IsNullOrWhiteSpace((string) currentValue.FieldInfo.GetValue(e.Entity)))
currentValue.FieldInfo.SetValue(e.Entity, null);
}
- 1. 實體框架試圖將空字符串保存爲空數據庫
- 2. LINQ實體框架值不能爲空。參數名:字符串
- 3. 實體框架:調用SaveChanges後字符串屬性爲空
- 4. 具有實體框架的空間MySQL
- 5. 使用實體框架保存空字符串,將字符串保存爲空格?
- 6. 實體框架 - 嵌套實體爲空
- 7. 實體框架 - 期待'providerInvariantName'參數的非空字符串
- 8. 實體框架預先加載多層次,沒有字符串
- 9. ASP.NET實體框架,如果空字符串 - 包含
- 10. 實體框架和SQL Server在字符串中添加空格?
- 11. 實體框架 - 選擇具有空值檢查的單列
- 12. 有沒有什麼辦法檢查字符串是空還是空?
- 13. 實體框架:選擇空值或值
- 14. 主鍵上的實體框架爲空
- 15. 類庫中的實體框架爲空
- 16. 沒有實體框架
- 17. 實體框架 - 將「可空」整數設置爲空
- 18. requiredif實體框架空場
- 19. 實體框架空對象
- 20. 實體框架 - 如何連接沒有LINQ和只有字符串的表?
- 21. 實體框架和可空字段
- 22. 實體框架 - DbSet包含空實體
- 23. MVC實體框架當爲空時從其他實體中選擇字段
- 24. 截斷沒有空白的字符串
- 25. 查找沒有空字符串的行
- 26. 沒有空字符串的Django CharField
- 27. 實體框架的導航屬性在爲空之後爲空
- 28. 實體框架中的不可爲空導航屬性爲空
- 29. 將空(ish)字符串轉換爲空的最有效方法
- 30. 的實體框架連接字符串
從另外一個論壇上,我得到這個答案http://msdn.microsoft.com/en-us/library/vstudio/ms366709(v=vs.100).aspx(ConvertEmptyStringToNull屬性) – Naomi 2014-09-29 15:44:31
嗨納奧米,我很高興你找到了它,爲什麼不自己回答? – Shimmy 2014-09-30 23:27:07