Toubles with "Transient Properties"

4 posts, 2 answers
  1. Felix
    Felix avatar
    5 posts
    Member since:
    Nov 2012

    Posted 08 Nov 2013 Link to this post

    I'm using Windows 7 x64, Visual Studio 2012 Update 3, Telerik OpenAccess Q3 2013, MySQL 5.6, .NET 4.5 and C#.

     

    I've done two tables in MySQL.

     

    • Person
      • It contains
        • Id, as integer, not null, auto incremet and primary key.
        • Name, as varchar, lenght 45, not null.
        • LastName, as varchar, lenght 45, not null.
        • Sex, as char, lenght 1, not null.
    • Student
      • It contains
        • Id, as integer, not null, and primary key.
        • Career, as varchar, lenght 45, not null.

    There is a foreign key for the Id of Student, it depends on Id of Person.

    I've defined a transient property for person, SexNamed. While Sex can be 'M' (Male) of 'F' (Female), SexNamed identifies if Sex is 'M' or 'F' and returns Male or Female accordingly. SexNamed is not in the database (neither I want it to be there).

    When I try to use this transient property on anonymous type declaration in a from clause of C#, it gives an exception.

    I've prepared a test solution for a better understanding of the exception.

    http://s000.tinyupload.com/?file_id=75044529052440576873

  2. Answer
    Boris Georgiev
    Admin
    Boris Georgiev avatar
    190 posts

    Posted 13 Nov 2013 Link to this post

    Hi Felix,

    The exception is thrown because db.Students is of type IQueryable and the select statement will be executed on the server. But the property "SexNamed" is not mapped to any column in the database and cannot be resolved when the anonymous type is created. This property will be populated for the "Person", when the object is loaded in the cache.

    I could recommend you two workarounds:
    1) If you are using the "SexNamed" property only to create the anonymous type, you can insert the logic in the select statement when the anonymous type is created:
    var students = from student in db.Students
                    select new
                    {
                        SexNamed = student.Person.Sex == 'm' ? "male" : "female",
                        student.Career,
                        student.Id
                    };

    2) If you are using the "SexNamed" property in other places, you could load the "Person" object instead the property and to access it through the referenced object:
    var students = from student in db.Students
                    select new
                    {
                        student.Person,
                        student.Career,
                        student.Id
                    };
    MessageBox.Show(students.First().Person.SexNamed);

    I hope that helps.
     
    Regards,
    Boris Georgiev
    Telerik
    OpenAccess ORM Q3 2013 simplifies your model operations even further providing you with greater flexibility. Check out the list of new features shipped with our latest release!
  3. DevCraft banner
  4. Felix
    Felix avatar
    5 posts
    Member since:
    Nov 2012

    Posted 14 Nov 2013 Link to this post

    I was kinda expecting that answer...

    I've some complex transient properties for wich adding the code in the anonymous type declaration generates a big amount of code. Instead, I'm putting some extension methods in there. For example:
    internal static class EntityPerson
    {
        public static string SexNamed(this Person entity)
        {
            return SexNamed(entity.Sexo);
        }
      
        public static string SexNamed(char sex)
        {
            return sex == 'M'
                ? "Male"
                : "Female";
        }
    }

    Then I just put any of the extension methods in the anonymous type declaration

    I've also found that this code works:
    using (var db = new FluentModelTransientError())
    {
        var students = from student in (IEnumerable<Student>) db.Students
            select new
            {
                student.Person.SexNamed,
                student.Career,
                student.Id
            };
        MessageBox.Show(students.First().SexNamed);
    }

    The only but is that the two previous alternatives, including the alternative in the post #2, generates a lot of SQL queries being executed if there are lots of records, even with the ToList call.

    I've done some things here and there and I've optimized it for executing only one SQL. The idea is to select all the needed stuff in a from clause and make the ToList call there (it assures only one SQL bein executed). With the created object of type IList<AnonymousType>, apply methods like SexNamed(char sex) for getting some "transient" properties.

    Thanks for support!
  5. Answer
    Boris Georgiev
    Admin
    Boris Georgiev avatar
    190 posts

    Posted 19 Nov 2013 Link to this post

    Hello Felix,

    I am glad to see you have managed to resolve the issues on your side. 

    You should have in mind that you will hit a performance issue casting an IQueryable to IEnumerable. The statement will also have deferred execution but the difference will be if you have filtering. The IQueryable statement will be executed in the database as opposed of the IEnumerable statement which will load the objects in the database and then the filter will be applied on the loaded objects.

    If any other questions arise, do not hesitate to contact us.

    Regards,
    Boris Georgiev
    Telerik
    OpenAccess ORM Q3 2013 simplifies your model operations even further providing you with greater flexibility. Check out the list of new features shipped with our latest release!
Back to Top