I'm just a junior developer, so please don't judje hard. I started implement my solution by declaring classes that will represent my dbase records.

namespace OrmObj
{
    class Person : Entity
    {
        [Key, Field]
        public int Id { get; private set; }

        [Field]
        public string Name { get; set; }

        [Field]
        public int Age { get; set; }

        [Field]
        public EntitySet<Pet> Pets { get; set; }

        public override string ToString()
        {
            return String.Format("I'm {0} {1} yers old, I have {2} pets", this.Name, this.Age, this.Pets.Count);
        }

        public Person(Session session, string name, int age) : base(session)
        {
            this.Name = name;
            this.Age = age;
        }

        public Person(Session session) : this(session, "Anonimus", 25)
        {
        }
    }

    class Pet : Entity
    {
        [Key, Field]
        public int Id { get; private set; }

        [Field]
        public string Name { get; set; }

        [Field]
        public int Age { get; set; }

        public Pet(Session session, string name, int age) : base(session)
        {
            this.Name = name;
            this.Age = age;
        }

        public Pet(Session session) : this(session, "Unknown", 5)
        {
        }

    }

}

Here's the database access logic.

private static string magicOne = "Data Source=localhost; Initial Catalog=DataObjectsTest;MultipleActiveResultSets=True;User Id=sa;Password=sa";
private static string sqlserver = "sqlserver";

static void Main(string[] args)
{
    var config = new DomainConfiguration(sqlserver, magicOne);
    config.Types.Register(typeof(Person).Assembly);
    config.Types.Register(typeof(Pet).Assembly);
    var domain = Domain.Build(config);
    using (var session = domain.OpenSession())
    {
        using (var txact = session.OpenTransaction())
            {
                var cat1 = new Pet(session, "Cake", 3);
                var cat2 = new Pet(session, "Fiona", 5);
                var person = new Person(session, "Eric", 42);

                person.Pets.Add(cat1);
                person.Pets.Add(cat2);

                txact.Complete();
            }
    }

}

I cought "Type 'Pet' is not registered." exception. And that is strange becouse I definitely can see my Pet and Person classes registered in config variable

asked Jul 12 at 06:52

Kirill's gravatar image

Kirill
713

edited Jul 12 at 06:55


One Answer:

Hello Kirill,

First of all you need to make Pet and Person public. If you don't declare them as public explicitly they will be treated by compiler as private classes. As you probably know private classes aren't usable by other assemblies.

Also you need to mark Pet and Person by [HierarchyRootAttribute]. This attribute declares the root of the types hierarchy. Hierarchy roots and all types derived from them will be represented in database as tables, they also can be used in Session.Query.All<t>() for querying data from database. Types which are not in some hierarchy won't be included in domain.

For example,

public abstract class SomeBaseEntity : Entity
{
  [Field, Key]
  public long Id{get; private set;}

[Field] public DateTime CreationDate {get; set;}

public (Session session) : base (session) { CreationDate = DateTime.UtcNow; } }

[HierarchyRoot] public class Pet : SomeBaseEntity { // Id and CreationDate will be inherited from SomeBaseEntity // no need to declare them one more time. [Field] public string Name{get;set;}

public Pet(Session session, string name) : base (session) { Name = name } }

public enum DogSpecies { One, Two, Three, DontKnow }

public class Dog : Pet { [Field] public DogSpecies TypeOfDog {get;set;}

public Dog(Session session, string name, DogSpecies typeOfDog) :base(session, name) { TypeOfDog = typeOfDog; } }

If you register these types then after domain building is finished you will have tables - Pet(Id, CreationDate, Name) and Dog(Id, TypeOfDog). SomeBaseEntity won't be represented as a table. But as you can see all its field will be in Pet. You can query all pets(if you have not only dogs) or dogs specifically

using (var session = domain.OpenSession())
using (var tx = session.OpenTransaction())
{
  foreach(var pet in session.Query.All<Pet>()) {
    Console.WriteLine("My name is {0} and I'm a {1}", pet.Name, pet.GetType().Name);
  }
  foreach(var dog in session.Query.All<Dog>()) {
    Console.WriteLine("I'm {0} and I can bark", dog.Name);
  }
  //this will throw exception
  //foreach(var t in session.Query.All<SomeBaseEntity>()) {
  //  Console.WriteLine("I'm {0} with number '{1}'", t.GetType().Name, t.Id);
  //}
}

Another examle,

[HierarchyRoot]
public abstract class SomeBaseEntity : Entity
{
  [Field, Key]
  public long Id{get; private set;}

[Field] public DateTime CreationDate {get; set;}

public (Session session) : base (session) { CreationDate = DateTime.UtcNow; } }

public class Pet : SomeBaseEntity { // Id and CreationDate will be inherited from SomeBaseEntity // no need to declare them one more time. [Field] public string Name{get;set;}

public Pet(Session session, string name) : base (session) { Name = name } }

public enum DogSpecies { One, Two, Three, DontKnow }

public class Dog : Pet { [Field] public DogSpecies TypeOfDog {get;set;}

public Dog(Session session, string name, DogSpecies typeOfDog) :base(session, name) { TypeOfDog = typeOfDog; } }

I just moved [HierarchyRoot] from Pet to SomeBaseEntity class. In this case, you will have three tables - SomeBaseEntity(Id, CreationDate), Pet(Id, Name) and Dog(Id, TypeOfDog) so I can do this

using (var session = domain.OpenSession())
using (var tx = session.OpenTransaction())
{
  foreach(var pet in session.Query.All<Pet>()) {
    Console.WriteLine("My name is {0} and I'm a {1}", pet.Name, pet.GetType().Name);
  }
  foreach(var dog in session.Query.All<Dog>()) {
    Console.WriteLine("I'm {0} and I can bark", dog.Name);
  }
  foreach(var t in session.Query.All<SomeBaseEntity>()) {
    Console.WriteLine("I'm a {0} with number '{1}'", t.GetType().Name, t.Id);
  }
}

DomainConfiguration.Types property represents all registered-to-process types. If you register an assembly you will see all the accessible types of the assembly in DomainConfiguration.Types, but they might be not included in domain. When domain is built you can also check persistent types which were included in domain in Domain.Model.Types. This collection has groups of elements like Entities, Structures, Interfaces.

You don't need to register one assembly twice. Pet and Person are in the same assembly, right?

answered Jul 26 at 09:30

Alexey%20Kulakov's gravatar image

Alexey Kulakov
51215

edited Jul 26 at 09:38

Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

Subscription:

Once you sign in you will be able to subscribe for any updates here

Tags:

×3

Asked: Jul 12 at 06:52

Seen: 407 times

Last updated: Jul 26 at 09:38

powered by OSQA