Вставка вложенного объекта через JSON с использованием веб-api с NHibernate

#.net-core #nhibernate #asp.net-core-webapi #fluent-nhibernate-mapping

#.net-ядро #nhibernate #asp.net-ядро-webapi #fluent-nhibernate-отображение

Вопрос:

Я пишу приложение, состоящее из ReadAPI и WriteAPI. API чтения содержит классы домена и использует код ядра EF сначала для генерации базы данных SQL и для чтения из нее.

API записи использует NHibernate для записи в базу данных, которая генерируется EF Core. До сих пор я вставлял «простой» объект через write API, который работал нормально.

Сейчас я столкнулся с проблемой. У меня есть доменный класс Driver, внутри которого есть вложенный объект Address. На уровне базы данных драйвер может иметь один адрес, а адрес может принадлежать нескольким драйверам. Я пытаюсь ОПУБЛИКОВАТЬ объект JSON, объект драйвера, через write API. На данный момент я решил вставить адрес, заранее создав запись адреса в базе данных и указав идентификатор адреса в JSON.

Что я хочу сделать сейчас, так это предоставить полный вложенный объект JSON и попросить NHibernate сгенерировать вставки для меня. Я перепробовал так много вещей, но чувствую, что у меня ничего не получается. Любой совет был бы очень признателен.

Я использую .Net Core с NHiberate 5.3.5, в котором уже есть функциональность отображения по коду. Если кто-то может решить эту проблему, используя вместо этого Fluent NH, это тоже хорошо, так как тогда я сам преобразовал его в нотацию NH 5.3.5.

Мой код:

Классы домена:

Драйвер:

 namespace Models
{
    public class Chauffeur : IIdentifiable
    {
        public virtual long Id { get; set; }
        public virtual string Naam { get; set; }
        public virtual string Voornaam { get; set; }
        public virtual DateTime GeboorteDatum { get; set; }
        //todo validatie
        public virtual string RijksRegisterNummer { get; set; }
        public virtual RijbewijsTypes TypeRijbewijs { get; set; }
        public virtual bool Actief { get; set; }

        //rel adres
        public virtual long AdresId { get; set; }
        public virtual Adres Adres { get; set; }

        //rel tankkaart
        public virtual long TankkaartId { get; set; }
        public virtual Tankkaart Tankkaart { get; set; }

    }
}
 

Адрес:

 namespace Models
{
    public class Adres : IIdentifiable
    {
        public virtual long Id { get; set; }
        public virtual string Straat { get; set; }
        public virtual int Nummer { get; set; }
        public virtual string Stad { get; set; }
        public virtual int Postcode { get; set; }
        public virtual ICollection<Chauffeur> Chauffeurs { get; set; }
    }
}
 

Моя карта драйверов до сих пор:

 namespace WriteAPI
{
    public class ChauffeurMap : ClassMapping<Chauffeur>
    {
        public ChauffeurMap()
        {
            this.Table("Chauffeurs");

            this.Id(c => c.Id, c =>
            {
                c.Generator(Generators.Native);
                c.Type(NHibernateUtil.Int64);
                c.Column("Id");
                c.UnsavedValue(0);
            });
            
            this.Property(c => c.Naam);
            this.Property(c => c.Voornaam);
            this.Property(c => c.GeboorteDatum);
            this.Property(c => c.RijksRegisterNummer);
            this.Property(c => c.TypeRijbewijs);
            this.Property(c => c.Actief);

            this.Property(c => c.AdresId);

            this.Property(c => c.TankkaartId);
        }
    }
}
 

Используя это сопоставление, я мог бы вставить вложенный объект, используя существующий идентификатор дочернего адреса.

Как я вставил это через сообщение:

 {
                "Naam" : "Bart",
                "Voornaam" : "Jannsses",
                "AdresId" : 4,
                "GeboorteDatum" : "1979-04-25",
                "RijksRegisterNummer" : "999-888-7777",
                "TypeRijbewijs" : 1,
                "Actief" : true
}
 

Как я хотел бы вставить его в будущем:

 {
                "Naam" : "Bart",
                "Voornaam" : "Jannsses",
                "Adres" : {
                    "Straat": "Boomstraat", 
                    "Nummer": 1, 
                    "Stad": "Gent", 
                    "Postcode": 9000
                          },
                "GeboorteDatum" : "1979-04-25",
                "RijksRegisterNummer" : "999-888-7777",
                "TypeRijbewijs" : 1,
                "Actief" : true
}
 

Обратите внимание, что идентификатор адреса автоматически генерируется на уровне базы данных.

Любая помощь была бы очень признательна.

С наилучшими пожеланиями

Комментарии:

1. Не могли бы вы поделиться кодом, в котором фактически происходит вставка базы данных? Это может помочь дать некоторый дополнительный контекст.

Ответ №1:

Вам нужно будет добавить ManyToOne сопоставление в свой ChauffeurMap класс

  this.ManyToOne(x => x.Adres , m =>
        {
            m.Column("AdresId");
            // AdresId can be insert and update
            m.Update(true);
            m.Insert(true);
            m.Cascade(Cascade.None);
            m.Fetch(FetchKind.Join);
            m.NotFound(NotFoundMode.Exception);
            m.Lazy(LazyRelation.Proxy);
            m.ForeignKey("AdresId");
        });
 

И вам также понадобится дополнительный класс сопоставления для Adres as AdresMap . Надеюсь, у вас это уже есть. Если нет, пожалуйста, добавьте его, как показано ниже —

 public class AdresMap : ClassMapping<Adres> 
{
    public AdresMap()
    {
    this.Table("Adres"); //Your table name
    this.Id(c => c.Id, c =>
        {
            c.Generator(Generators.Native);
            c.Type(NHibernateUtil.Int64);
            c.Column("Id");
            c.UnsavedValue(0);
        });

    Set(x => x.Chauffeurs, c =>
        {
            c.Key(k =>
                {
                    k.Column("Id");
                    k.ForeignKey("AdresId");
                });
            c.Inverse(true);
            c.Cascade(Cascade.None);
        },
        r => r.OneToMany(o => { }));

    this.Property(x => x.Straat );
    // ... other properties
   }
}