3

我正在尝试在我的网站上创建一个新帖子,但由于某种原因,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 自动填充。

4

0 回答 0