Children's Tables at NHibernate

Is there a way in NHibernate so that I can use the following objects

public class Person
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Pet> Pets { get; set; }
}

public class Pet
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}

And you don’t need to create a “special” AddPet method for Person to have pet children.

public void AddPet(Pet p)
{
    p.Person = this;
    Pets.Add(p);
}

_session.SaveOrUpdate(person);

It doesn’t save pets, because Pet has no reference to humans.

If I update "Home" to contain this link.

public class Pet
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual Person Person { get; set; }
}

On new pets, I still need to establish a Personality, it seems unnecessary for me, and also risky, because people can still call

person.Pets.Add(new Pet())

The only other possibility I can think of is a custom list that sets the parent link when adding child objects.

+3
source share
4 answers

( ):

public class Person
{
    private IList<Pet> pets;

    protected Person()
    {}

    public Person(string name)
    {
        Name = name;
        pets = new List<Pet>();
    }

    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IEnumerable<Pet> Pets
    {
        get { return pets; }
    }

    public virtual void AddPet(Pet pet)
    {
        pets.Add(pet);           
    }
}

public class Pet 
{
    protected Pet()
    {}

    public Pet(string name)
    {
        Name = name;
    }

    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
}

public class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        Id(x => x.Id).GeneratedBy.GuidComb();
        Map(x => x.Name);
        HasMany(x => x.Pets).Cascade.AllDeleteOrphan().Access.AsLowerCaseField();
    }
}

public class PetMap : ClassMap<Pet>
{
    public PetMap()
    {
        Id(x => x.Id).GeneratedBy.GuidComb();
        Map(x => x.Name);
    }
}

:

    [Test]
    public void CanSaveAndRetrievePetAttachedToPerson()
    {
        Person person = new Person("Joe");
        person.AddPet(new Pet("Fido"));

        Session.Save(person);

        Person retrievedPerson = Session.Get<Person>(person.Id);
        Assert.AreEqual("Fido", retrievedPerson.Pets.First().Name);
    }

.

, Fluent NHibernate.

+3

#

?

, -.

protected static void SetChildReferences(E parent)
{
    foreach (var prop in typeof(E).GetProperties(BindingFlags.Public | BindingFlags.Instance))
    {
        if (!prop.CanRead) continue;

        Type listType = null;
        foreach (Type type in prop.PropertyType.GetInterfaces())
        {
            if (type.IsGenericType &&
                type.GetGenericTypeDefinition() == typeof(ICollection<>))
            {
                listType = type.GetGenericArguments()[0];
                break;
            }
        }

        List<PropertyInfo> propsToSet = new List<PropertyInfo>();
        foreach (PropertyInfo childProp in 
            (listType ?? prop.PropertyType).GetProperties(BindingFlags.Public | BindingFlags.Instance))
        {
            if (childProp.PropertyType == typeof(E))
                propsToSet.Add(childProp);
        }

        if (propsToSet.Count == 0) continue;

        if (listType == null)
        {
            object child = prop.GetValue(parent, null);
            if (child == null) continue;
            UpdateProperties(propsToSet, child, parent);
        }
        else
        {
            ICollection collection = (ICollection)prop.GetValue(parent, null);
            foreach (object child in collection)
            {
                if (child == null) continue;
                UpdateProperties(propsToSet, child, parent);
            }
        }
    }
}

protected static void UpdateProperties(List<PropertyInfo> properties, object target, object value)
{
    foreach (PropertyInfo property in properties)
    {
        property.SetValue(target, value, null);
    }
}
0

, , ?

public void AddPet(Pet p)

Person

IEnumerable<Pets> Pets { get; }

. List . , person.Pets.Add(new Pet()) , .

0

NHibernate, . NHibernate .

I agree with gcores, make the list secure or private. Find a way to link your objects together. if it’s not as simple as implementing the add method, consider a separate service class or factory. (If it's even harder, try something like Spring.Net.)

By the way, NHibernate probably saved pets, but did not have the information to write the correct foreign key. Thus, he kept orphaned pets that never appeared on any person’s pets list.

0
source

Source: https://habr.com/ru/post/1703268/


All Articles