This is a migrated thread and some comments may be shown as answers.

Toubles with "Transient Properties"

3 Answers 46 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Felix
Top achievements
Rank 1
Felix asked on 09 Nov 2013, 03:53 AM

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

3 Answers, 1 is accepted

Sort by
0
Accepted
Boris Georgiev
Telerik team
answered on 13 Nov 2013, 05:35 PM
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!
0
Felix
Top achievements
Rank 1
answered on 14 Nov 2013, 05:32 PM
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!
0
Accepted
Boris Georgiev
Telerik team
answered on 19 Nov 2013, 04:01 PM
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!
Tags
General Discussions
Asked by
Felix
Top achievements
Rank 1
Answers by
Boris Georgiev
Telerik team
Felix
Top achievements
Rank 1
Share this question
or