Using Dynamic Linq with mixing types

16 posts, 0 answers
  1. Dmitry
    Dmitry avatar
    8 posts
    Member since:
    Oct 2012

    Posted 01 Aug 2013 Link to this post

    Hi.

    The documentation Mixing CLR Types and Artificial Properties describes how to create mixing types.
    But when I extend type with artificial properties new derived class isn't created. And I cannot select or filter artificial properties using Dynamic LINQ. It throws the following error: No property or field 'TestField' exists in type 'TestClass'

    How can I query (filter/selecting) mixing types?
  2. PetarP
    Admin
    PetarP avatar
    754 posts

    Posted 05 Aug 2013 Link to this post

    Hello Dmitry,

     Can you please share with us the code you are using to extend the model? 
    Basically extending the model with artificial types will generated them directly into an assembly. You will not actually see them in your solution as generated code. After this is done you should be able to query them successfully with dynamic linq. Can you please make sure that you are using the same names when querying? You can try to query with both field names and property names.

    Regards,
    Petar
    Telerik
    OpenAccess ORM Q2 2013 brings you a more powerful code generation and a unique Bulk Operations support with LINQ syntax. Check out the list of new functionality and improvements shipped with this release.
  3. DevCraft banner
  4. Dmitry
    Dmitry avatar
    8 posts
    Member since:
    Oct 2012

    Posted 06 Aug 2013 Link to this post

    As you requested.
    MetdataSource:
    public class FluentModelMetadataSource : FluentMetadataSource
    {
        protected override IList<MappingConfiguration> PrepareMapping()
        {
            List<MappingConfiguration> configurations = new List<MappingConfiguration>();
            MappingConfiguration<Person> personConfiguraiton = new MappingConfiguration<Person>();
            personConfiguraiton.MapType(p => new
            {
                PersonId = p.Id,
                LastName = p.LastName,
                FirstName = p.FirstName,
                Contact = p.Address
            }).ToTable("People");
            personConfiguraiton.HasProperty(p => p.Id).IsIdentity(KeyGenerator.Autoinc);
     
            personConfiguraiton.HasArtificialPrimitiveProperty<int>("Age");
            personConfiguraiton.HasArtificialProperty<byte[]>("Picture");
            configurations.Add(personConfiguraiton);
            return configurations;
        }
     
        protected override void SetContainerSettings(MetadataContainer container)
        {
            MetaNameGenerator nameGenerator = container.NameGenerator;
            nameGenerator.RemoveCamelCase = false;
            nameGenerator.SourceStrategy = NamingSourceStrategy.AutomaticProperty;
            nameGenerator.ResolveReservedWords = false;
            container.DefaultMapping.NullForeignKey = true;
        }
    }
    Person:
    public class Person
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Address { get; set; }
    }
    Using:
    using (var ctx = new FluentModel("MixingTestConn"))
    {
           var persons = ctx.GetAll<Person>();
           var queryByfirstName = persons.Where("FirstName = \"Olga\"");
           var queryBytAge = persons.Where("Age > 20"); //Error: No property or field 'Age' exists in type 'Person'
           var queryBytAge = persons.Where("age > 20"); //Error: No property or field 'age' exists in type 'Person'
    }


    Also
    ctx.GetAll<Person>() doesn't return properties Age and Picture which created by artificial Api.
    Thanks.
  5. PetarP
    Admin
    PetarP avatar
    754 posts

    Posted 09 Aug 2013 Link to this post

    Hello Dmitry,

     You said you are extending an already existing persistent type in your model? If I understood you correctly you should be merging this fluent generated model with your real model (probably an rlinq file). Is that the case? Or are you just trying to extend a normal persistent type with a few artificial properties?

    Regards,
    Petar
    Telerik
    OpenAccess ORM Q2 2013 brings you a more powerful code generation and a unique Bulk Operations support with LINQ syntax. Check out the list of new functionality and improvements shipped with this release.
  6. Andrew Lastochkin
    Andrew Lastochkin avatar
    14 posts
    Member since:
    Sep 2012

    Posted 20 Aug 2013 Link to this post

    Hello!

    I have the same problem. I have normal persistent type and want to add some artificial field.
    If I add it with artificial api I cannot query it and make filters using this property.

    Dynamic LINQ simply throws the following exception: "ExceptionMessage"No property or field 'EmployeeCode' exists in type 'User'".

    Because new derived class is not created for this persistent type and it doesn't have artificial field named EmployeeCode. 

    Andrey
  7. PetarP
    Admin
    PetarP avatar
    754 posts

    Posted 22 Aug 2013 Link to this post

    Hi Andrew,

     I will have to ask you the same. Can you please include the code you are using for extending the model? Are you merging your old model with your new model? If so, how?
    Any information you can share on this subject will be of great help as so far we are unable to reproduce this false behavior.

    Regards,
    Petar
    Telerik
    OpenAccess ORM Q2 2013 brings you a more powerful code generation and a unique Bulk Operations support with LINQ syntax. Check out the list of new functionality and improvements shipped with this release.
  8. Andrew Lastochkin
    Andrew Lastochkin avatar
    14 posts
    Member since:
    Sep 2012

    Posted 23 Aug 2013 Link to this post

    Hello!

    I attached tiny project that reproduces the problem. 
    Thank you for assistance!

    Link: https://disk.yandex.com/public/?hash=aSRqf11BLw9eNTGL4AZTLSAvYplcnRFkg6wWTA5SRx4%3D&locale=en


    Best Regards,
    Andrey
  9. PetarP
    Admin
    PetarP avatar
    754 posts

    Posted 28 Aug 2013 Link to this post

    Hi,

     The problem here is that when we are extending an already present type we cannot really add a field to the already compiled assembly. The way the artificial works is that we create a temp assembly where the type does have the field. However in your case the type is loaded from the original assembly where the field is indeed not present. What you can do to fix this is to slightly rewrite your query like this:

    var users = ctx.GetAll<User>().Where(x => x.FieldValue<int>("Age") > 10);
    This way using our extension method FIeldValue you can be sure that you are getting the correct value.

    Regards,
    Petar
    Telerik
    OpenAccess ORM Q2 2013 brings you a more powerful code generation and a unique Bulk Operations support with LINQ syntax. Check out the list of new functionality and improvements shipped with this release.
  10. Andrew Lastochkin
    Andrew Lastochkin avatar
    14 posts
    Member since:
    Sep 2012

    Posted 28 Aug 2013 Link to this post

    Oh, Petar, thanks! That's great!

    But how can I get the same with Dynamic LINQ? 
  11. Andrew Lastochkin
    Andrew Lastochkin avatar
    14 posts
    Member since:
    Sep 2012

    Posted 29 Aug 2013 Link to this post

    Figured out about DynamicLINQ and modified some LINQ-library code. Now I can do that this way:
    var users = ctx.GetAll("MixingTypesTest.User").Where("val_int(Age) > 10").Select("new (val(Age) as w)").OfType<object>().ToArray();
    And it does work.

    If this may seem interesting to someone modified Dynamic.cs available here: http://yadi.sk/d/vrQxLwZi8TaWS
    Format of call: val(XXX) or val_TYPE(XXX) 
    For example: val_long(Age), val_int(Height), val(Age)
    If type name is not specified then object is implied.


  12. PetarP
    Admin
    PetarP avatar
    754 posts

    Posted 02 Sep 2013 Link to this post

    Hello Andrew,

     That is a good solution should you want to use the dynamic linq way. We still advice you to stick to our API in the cases that you can but if your scenario does not allow that then your solution should work out just fine.

    Regards,
    Petar
    Telerik
    OpenAccess ORM Q2 2013 brings you a more powerful code generation and a unique Bulk Operations support with LINQ syntax. Check out the list of new functionality and improvements shipped with this release.
  13. Andrew Lastochkin
    Andrew Lastochkin avatar
    14 posts
    Member since:
    Sep 2012

    Posted 17 Dec 2013 Link to this post

    Hello!

    I have static type (enhanced and mapped) to which I add in runtime artificial association property to some artificial class. To construct query for this association field I have to use dynamic constructed expression with ExtensionMethods.FieldValue<T> method. But when T is artificial type the following exception occurs:
    ExceptionMessage: "Specified method is not supported.",
    ExceptionType: "System.NotSupportedException",
    StackTrace: " at System.Reflection.Emit.MethodBuilderInstantiation.GetParameters()
    at System.Dynamic.Utils.TypeExtensions.GetParametersCached(MethodBase method)
    at System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ReadOnlyCollection`1& arguments)
    at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)

    It occurs due to runtime creation of generic method with artificial type T. But .NET have limitations in implementation of this feature.

    Can you please add non-generic version of FieldValue method that takes type as second argument? Or are there any other solutions?
  14. Viktor Zhivkov
    Admin
    Viktor Zhivkov avatar
    291 posts

    Posted 18 Dec 2013 Link to this post

    Hello Andrew,

    Can you provide us with the code of the mapping and the value extraction that is causing the exception?
    You can attach either a complete project or just the code snippets for the normal type and artificial type mappings and the query that attempts to read the values from the database.

    Based on the description that you have posted I suppose that you have a navigation property between two artificial types. Am I correct?

    Regards,
    Viktor Zhivkov
    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!
  15. Andrew Lastochkin
    Andrew Lastochkin avatar
    14 posts
    Member since:
    Sep 2012

    Posted 18 Dec 2013 Link to this post

    Hello, Viktor!

    Trying to explain more clearly:
    1. I have a normal type (User)
    2. I create an artificial type (Department). Department is artificial runtime type 
    3. I create navigation artificial property from normal type to artificial type (User.DepartmentFk -> Department)
    4. When I am trying to get property from artificial type I am getting an error (User.FieldValue<Department>("DepartmentFk").Title).

    Department is artificial type and I cannot access it in static way. I have to construct ExpressionTree in runtime to create correct LINQ query.
    But when I do this, the exception occurs. The code snippet:

    var method = typeof(ExtensionMethods).GetMethod("FieldValue").MakeGenericMethod(artificialDepartmentType);
    return Expression.Call(null, method, new[] { instance, Expression.Constant("DepartmentFk") });

    If you do not understand or do not reproduce the problem I will try to create small solution.
  16. Viktor Zhivkov
    Admin
    Viktor Zhivkov avatar
    291 posts

    Posted 20 Dec 2013 Link to this post

    Hello Andrew,

    Thanks for the detailed information.
    I believe that you can accomplish the same result using a lot simpler code by using FieldValue<object> rather than  building a new generic method with the correct artificial type.
    I have prepared a small demo application that reproduces the scenario that I believe you have described. You can find it attached. In the sample I am using the latest version of OpenAccess, but the required API is available already in the version you may be using (2013.2.702 if I am correct).

    If you think I have misinterpreted your scenario, please let us know so we can alter the approach to suit better your needs.

    Regards,
    Viktor Zhivkov
    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!
  17. Andrew Lastochkin
    Andrew Lastochkin avatar
    14 posts
    Member since:
    Sep 2012

    Posted 21 Dec 2013 Link to this post

    Viktor,

    Thank you very much. It is great and working idea!

    OpenAccess - very cool thing too. Thank you again.
Back to Top
DevCraft banner