我正在尝试在我的网站上创建一个新帖子,但由于某种原因,EF 抛出以下错误:
来自“PostAttributeValue_Definition”AssociationSet 的关系处于“已删除”状态。给定多重约束,相应的“PostAttributeValue_Definition_Source”也必须处于“已删除”状态。
由于我没有尝试删除任何内容,也没有更改或删除任何值,所以我很困惑为什么会收到此错误。
我的数据库上下文包含以下内容:
modelBuilder.Entity<PostAttributeValue>().HasRequired<PostAttributeDefinition>(a => a.Definition).WithOptional().Map(m =>
{
m.MapKey("RelatedAttributeDefinitionId");
}).WillCascadeOnDelete(false);
/* Category(required) to PostAttributeDefinition(many) */
modelBuilder.Entity<PostAttributeDefinition>().HasRequired<Category>(a => a.OwnerCategory).WithMany(c => c.AttributeDefinitions).Map(m =>
{
m.MapKey("OwnerCategoryId");
}).WillCascadeOnDelete(true);
我的发布方法如下所示:
//
// POST: /Post/Publish/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Publish(int? id, PublishViewModel model)
{
if (!id.HasValue || id.Value < 1)
{
return HttpNotFound();
}
var category = this.categoryService.Find(id.Value);
if (category == null)
{
return HttpNotFound();
}
if (ModelState.IsValid)
{
List<PostAttributeValue> attributes = new List<PostAttributeValue>();
foreach (var attribute in model.Attributes)
{
attributes.Add(new PostAttributeValue()
{
Definition = attribute.Definition,
RawValue = attribute.Value.Serialize()
});
}
Post post = new Post()
{
Title = model.Title,
Description = model.Description,
City = model.City.City,
Brokerage = model.Brokerage,
Location = model.Location,
RequestedPrice = model.Price.Value,
ParentCategory = category,
Attributes = attributes,
};
this.postService.PublishPost(post);
return RedirectToAction("ImageSelection", new { id = post.PostIdentifier });
}
return View(model);
}
错误是从 Repository 类 Add() 方法引发的,如下所示:
public TEntity Add(TEntity entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
try
{
var result = this.Entity.Add(entity);
this.context.SaveChanges();
return result;
}
catch
{
var deletedEntries = context.ChangeTracker.Entries().Where(e => e.State != EntityState.Added && e.State != EntityState.Unchanged);
throw;
}
}
因为异常与处于已删除状态的实体有关,所以我编写了这个 linq 查询来检查未更改或添加的实体,但它返回零结果......我真的不知道为什么我会收到这个错误.
需要注意的是,我正在使用代理实体,从调试器中的检查来看,一切似乎都很好——整个值都被填写为例外。
希望有人能帮我弄清楚。谢谢!:)
编辑:
PostAttributeDefinition 模型类,这是一个描述自定义属性定义的类(每个类别可以有不同的自定义属性 - 例如,“TV Shows”可以有自定义属性“Number of episodes”,而 Movies“IMDB rank”,例如)
public class PostAttributeDefinition
{
#region Members
private Lazy<object> lazyDataValue = null;
private Lazy<PostAttributeDefinitionValidationRules> lazyValidatorValue = null;
private Type cachedDataType;
#endregion
/// <summary>
/// The filter name
/// </summary>
[Key]
public int DefinitionId { get; set; }
/// <summary>
/// The owner category
/// </summary>
[Required]
public virtual Category OwnerCategory { get; set; }
/// <summary>
/// The filter title
/// </summary>
[Required]
public string Title { get; set; }
/// <summary>
/// Metadata enum that provides extra data about the data type
/// </summary>
public PostAttributeTypeMetadata TypeMetadata { get; set; }
/// <summary>
/// Bitwise metadata that provides data about the object in display mode
/// </summary>
public PostAttributeDisplayModeMetadata DisplayModeMetadata { get; set; }
public PostAttributeEditorType EditorType { get; set; }
/// <summary>
/// The attribute raw default value
/// </summary>
[Required]
public byte[] RawDataValue { get; set; }
/// <summary>
/// The attribute raw associated validation attributes
/// </summary>
/// <remarks>
/// This field is used only by EF.
/// YES - It's against DDD rules, and I need to seperate it. setting it in TODO.
/// </remarks>
public byte[] RawValidationRules { get; set; }
/// <summary>
/// Is this field required
/// </summary>
/// <remarks>
/// This field does not relate to the validation rules since we should check it
/// only in creation / modification of the post and not in search for example.
/// </remarks>
public bool IsRequired { get; set; }
/// <summary>
/// The attribute validators
/// </summary>
public PostAttributeDefinitionValidationRules ValidationRules
{
get
{
if (lazyValidatorValue == null)
{
lazyValidatorValue = new Lazy<PostAttributeDefinitionValidationRules>(() =>
{
if (this.RawValidationRules == null || this.RawValidationRules.Length == 0)
{
return new PostAttributeDefinitionValidationRules();
}
return this.RawValidationRules.Deserialize() as PostAttributeDefinitionValidationRules;
});
}
return lazyValidatorValue.Value;
}
set
{
this.RawValidationRules = value.Serialize();
this.lazyValidatorValue = null;
}
}
/// <summary>
/// Get the stored object data type
/// </summary>
public Type ValueDataType
{
get
{
// Make sure we've loaded the serialized value
if (lazyDataValue == null)
{
RetriveDataValue();
}
return cachedDataType;
}
}
#region Value content
/// <summary>
/// Store the attribute default value
/// </summary>
/// <typeparam name="TType">The default value type</typeparam>
/// <param name="value">The default value</param>
/// <returns>Fluent style writing - returning the same object</returns>
public PostAttributeDefinition StoreDataValue<TType>(TType value)
{
// In case of empty value, we need to defaultize it
if (value == null)
{
value = value.DefaultizeNullableValueForSerialize<TType>();
}
// Store as bytes
RawDataValue = value.Serialize<TType>();
// Reset the lazy cached value
lazyDataValue = null;
// Fluent style returned value
return this;
}
/// <summary>
/// Retrive the item default value
/// </summary>
/// <typeparam name="TType">The item default value data type</typeparam>
/// <returns>The item default value</returns>
/// <exception cref="InvalidOperationException">Thrown in case the raw value is null or empty.</exception>
public TType RetriveDataValue<TType>()
{
return (TType)RetriveDataValue();
}
/// <summary>
/// Retrive the item default value
/// </summary>
/// <returns>The item default value</returns>
/// <exception cref="InvalidOperationException">Thrown in case the raw value is null or empty.</exception>
public object RetriveDataValue()
{
// Make sure that we've loaded the lazy value
if (lazyDataValue == null)
{
lazyDataValue = new Lazy<object>(() =>
{
// Deserialize
var value = RawDataValue.Deserialize();
// Remve defaultize in case we've done that (by the way, we're caching the type
// in order to retrive it in case of null value)
value = value.ReverseDefaultizeNullableValueForDeSerialize(out cachedDataType);
// Return it
return value;
});
}
// Return the cached lazy data value
return lazyDataValue.Value;
}
#endregion
}
我希望保存并导致问题的 PostAttributeValue 类是:
public class PostAttributeValue
{
/// <summary>
/// The attribute value id
/// </summary>
[Key]
public int AttributeValueId { get; set; }
/// <summary>
/// The value owner post
/// </summary>
public virtual Post OwnerPost { get; set; }
/// <summary>
/// The value attribute definition id
/// </summary>
//public int RelatedAttributeDefinitionId { get; set; }
/// <summary>
/// The value attribute definition
/// </summary>
public virtual PostAttributeDefinition Definition { get; set; }
/// <summary>
/// The stored raw value
/// </summary>
public byte[] RawValue { get; set; }
#region Value content
/// <summary>
/// Check if there's anything stored in the raw value
/// </summary>
/// <returns>Boolean value indicates if there's anything stored in the raw value</returns>
public bool HasValue()
{
return RawValue != null;
}
/// <summary>
/// Retrive the item value
/// </summary>
/// <typeparam name="TType">The item default value data type</typeparam>
/// <returns>The item value</returns>
/// <exception cref="InvalidOperationException">Thrown in case the raw value is null or empty.</exception>
public TType RetriveValue<TType>()
{
return (TType)RetriveValue();
}
/// <summary>
/// Retrive the item value
/// </summary>
/// <returns>The item value</returns>
/// <exception cref="InvalidOperationException">Thrown in case the raw value is null or empty.</exception>
public object RetriveValue()
{
if (RawValue == null)
{
throw new InvalidOperationException("Could not deserialize the value since there's nothing in the raw value.");
}
return RawValue.Deserialize();
}
#endregion
}
请注意,我使用 ViewModel 作为属性(model.Attributes 是一个 IEnumerable)
public class PostAttributeViewModel
{
[ReadOnly(true)]
[Editable(false)]
public PostAttributeDefinition Definition { get; set; }
[Required]
public int DefinitionId { get; set; }
[Required]
public string DefinitionVertificationToken { get; set; }
public object Value { get; set; }
}
我分配并映射到 PostAttributeValue 模型的定义属性由 EF 自动填充。