本文介绍了当一个实体与另一个实体有多个0..1:n关系时,如何使用Fluent API定义它们?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Azure移动服务,在我的模型中,我有一个实体消息,该实体与以下语句相关:

I'm working on an Azure Mobile Service and in my model I have an entity Message, which is related to itself following this statement:

  • 消息可能有一个父消息消息可能是许多消息的父.
  • A Message may have a parent Message, a Message may be the parent to many Messages.

我的班级定义如下:

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映射了这两个类:

I mapped this two classes using AutoMapper like this:

        /*
         * 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配置是:

And my Fluent API configuration for this is:

        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);

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

But when I try to insert a new Message I get the following error:

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

From this error I'm understanding that my Message is expecting to have a Parent, but since this would be the first Message there's no Parent, also not every Message will have a parent. In my Fluent API configuration I defined the Parent property as required, because when I set it to optional, when trying to insert a Message I got the following error:

我发送给端点的JSON是以下内容:

The JSON I'm sending to the endpoint is the following:

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

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

How can I set my configuration to define an optional property in this scenario or any other where an option property should be present?

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

So I checked and read this when dealing with a situation where an entity has two relationships with other entity, I added the InverseProperty annotations and got the following error:

据我所知,该错误是指存在循环引用,我想这可能是来自Parent属性,也可能是来自与Message的用户关系,但我不确定.

From what I remember, this error refers to a circular reference being present, I guess it's from either the Parent property or maybe either of the User relationships with Message, but I'm not really sure.

此错误的原因是什么?

推荐答案

出现以下错误:

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

Is due to the Parent property in message not being nullable. Take notice this is on the Model class, not the DTO, since string is already a nullable type.

所以在Message中,我必须更改:

So in Message I had to change:

    public int ParentId { get; set; }

为此:

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

这使我可以在POST端点上插入消息.

And this allows me to insert Messages on my POST endpoint.

这篇关于当一个实体与另一个实体有多个0..1:n关系时,如何使用Fluent API定义它们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 03:08