3

我正在开发 Azure 移动服务,在我的模型中,我有一个实体Message,它在以下语句之后与自身相关:

  • 一个消息可能有一个父消息,一个消息可能是许多消息的父消息

我的班级定义如下:

public partial class Message
{
    public Message()
    {
        this.Messages = new HashSet<Message>();
    }

    public int Id { get; set; }
    public int CreatedById { get; set; }
    public int RecipientId { get; set; }
    public int ParentId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public int MessageTypeId { get; set; }
    public Nullable<MessageType> Type { get; set; }
    public Nullable<bool> Draft { get; set; }
    public Nullable<bool> Read { get; set; }
    public Nullable<bool> Replied { get; set; }
    public Nullable<bool> isDeleted { get; set; }

    [JsonIgnore]
    public virtual User CreatedBy { get; set; }
    [JsonIgnore]
    public virtual User Recipient { get; set; }
    [JsonIgnore]
    public virtual ICollection<Message> Messages { get; set; }
    [JsonIgnore]
    public virtual Message Parent { get; set; }
}

我的 DTO 是这样的:

public class MessageDTO : EntityData 
{
    public string CreatedById { get; set; }
    public string RecipientId { get; set; }
    public string ParentId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public string Type { get; set; }
    public Nullable<bool> Draft { get; set; }
    public Nullable<bool> Read { get; set; }
    public Nullable<bool> Replied { get; set; }
    public Nullable<bool> isDeleted { get; set; }

}

我使用 AutoMapper 映射这两个类,如下所示:

        /*
         * Mapping for Message entity
         */
        cfg.CreateMap<Message, MessageDTO>()
            .ForMember(messageDTO => messageDTO.Id, map => map.MapFrom(message => MySqlFuncs.LTRIM(MySqlFuncs.StringConvert(message.Id))))
            .ForMember(messageDTO => messageDTO.ParentId, map => map.MapFrom(message => MySqlFuncs.LTRIM(MySqlFuncs.StringConvert(message.ParentId))))
            .ForMember(messageDTO => messageDTO.CreatedById , map => map.MapFrom(message => MySqlFuncs.LTRIM(MySqlFuncs.StringConvert(message.CreatedById ))))
            .ForMember(messageDTO => messageDTO.RecipientId, map => map.MapFrom(message => MySqlFuncs.LTRIM(MySqlFuncs.StringConvert(message.RecipientId))))
            .ForMember(messageDTO => messageDTO.Type, map => map.MapFrom(message => Enum.GetName(typeof(MessageType), message.MessageTypeId)));

        cfg.CreateMap<MessageDTO, Message>()
            .ForMember(message => message.Id, map => map.MapFrom(messageDTO => MySqlFuncs.LongParse(messageDTO.Id)))
            .ForMember(message => message.ParentId, map => map.MapFrom(messageDTO => MySqlFuncs.LongParse(messageDTO.ParentId)))
            .ForMember(message => message.CreatedById , map => map.MapFrom(messageDTO => MySqlFuncs.LongParse(messageDTO.CreatedById )))
            .ForMember(message => message.RecipientId, map => map.MapFrom(messageDTO => MySqlFuncs.LongParse(messageDTO.RecipientId)));

我的 Fluent API 配置是:

        this.Property(m => m.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        this.HasRequired(m => m.Parent).WithMany(p => p.Messages).WillCascadeOnDelete(true);
        this.HasRequired(m => m.Recipient).WithMany(u => u.MessagesReceived).WillCascadeOnDelete(false);
        this.HasRequired(m => m.CreatedBy).WithMany(u => u.MessagesCreated).WillCascadeOnDelete(false);

但是当我尝试插入新消息时,出现以下错误:

操作失败并出现以下错误:“MobileServiceContext.Messages”中的实体参与“Message_CreatedBy”关系。找到 0 个相关的“Message_CreatedBy_Target”。1 'Message_CreatedBy_Target' 是预期的。

从这个错误中,我了解到我的Message期望有一个Parent,但是由于这将是第一条Message,所以没有Parent,也不是每个Message都会有一个父级。在我的Fluent API配置中,我根据需要定义了Parent属性,因为当我将其设置为可选时,在尝试插入消息时出现以下错误:

在模型生成过程中检测到一个或多个验证错误:FollowAppApi.Models.Message_Parent: : 多重性与关系“Message_Parent”中角色“Message_Parent_Target”中的引用约束冲突。因为从属角色中的所有属性都不可为空,所以主体角色的多重性必须为“1”。

我发送到端点的 JSON 如下:

{
  "createdById": "1",
  "recipientId": "2",
  "title": "sample string 4",
  "content": "sample string 5",
  "type": "Alert",
  "draft": true,
  "read": true,
  "replied": true,
  "isDeleted": false
}

如何设置我的配置以在这种情况下或任何其他应存在选项属性的情况下定义可选属性?

编辑 1

所以我在处理一个实体与另一个实体有两个关系的情况时检查并阅读了这个,我添加了 InverseProperty 注释并得到以下错误:

操作失败并出现以下错误:“无法确定相关操作的有效排序。由于外键约束、模型要求或存储生成的值,可能存在依赖关系。

据我记得,这个错误是指存在一个循环引用,我猜它来自 Parent 属性或者可能是 User 与 Message 的关系,但我不太确定。

这个错误的原因是什么?

4

2 回答 2

2

所以出现以下错误:

操作失败并出现以下错误:“无法确定相关操作的有效排序。由于外键约束、模型要求或存储生成的值,可能存在依赖关系。

是由于消息中的 Parent 属性不可为空。请注意,这是在 Model 类上,而不是 DTO,因为 string 已经是可为空的类型。

所以在 Message 我不得不改变:

    public int ParentId { get; set; }

为了这:

    public Nullable<int> ParentId { get; set; }

这允许我在我的 POST 端点上插入消息。

于 2015-01-20T16:13:41.970 回答
1

当您有自引用对象时,您需要手动提供外键属性。

this.HasOptional(m => m.Parent) .WithMany(p => p.Messages) .HasForeignKey(m => m.ParentId) .WillCascadeOnDelete(true);

于 2015-01-19T23:34:15.780 回答