store.Select<TestTable> with oneToMany relation throw ArgumentException

Oct 18, 2012 at 10:05 AM

Hi,

I use OpenNETCF ORM on a windows mobile 6 device with .NET compact framework and SQLite database.

My project works well (Store creation, Insert, Select,...) on tables with no relation. I tried to add a one to many relation between two of them as describe in the documentation

Here is the code i added for the relation : One "Position" can have several "Location": 

Position.cs

[Reference(typeof(Location), "positionId", Autofill = true)]       

public Location[] locations { get; set; }

 

Position.cs

[Field]       

public int positionId { get; set; }

The insert works well and in the database the id are related ok.

The problem is when I try to select my positions with the location hydrated. it raises an "ArgumentException" :

Position[] positions = store.Select<Position>(true);

Here is the stack trace :

à System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean verifyAccess, StackCrawlMark& stackMark)à System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)à System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)à System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)à OpenNETCF.ORM.SQLStoreBase`1.FillReferences(Object instance, Object keyValue, ReferenceAttribute[] fieldsToFill, Boolean cacheReferenceTable)à OpenNETCF.ORM.SQLiteDataStore.Select(Type objectType, IEnumerable`1 filters, Int32 fetchCount, Int32 firstRowOffset, Boolean fillReferences)à OpenNETCF.ORM.SQLStoreBase`1.Select(Type objectType, String searchFieldName, Object matchValue, Int32 fetchCount, Int32 firstRowOffset, Boolean fillReferences)à OpenNETCF.ORM.SQLStoreBase`1.Select[T](Boolean fillReferences)à NEXCAPUP_PDA.Program.Main()

Oct 18, 2012 at 1:33 PM

I debugged the reference "OpenNETCF.ORM.SQLite" and found 2 things :

In SQLStoreBase.cs line 897 :                  

if (keyValue.Equals(childKey))
{
      children.Add(child);
}

I can see the value are equal but the condition is not valid so the child is not added to children... I don't know why. I forced the child to be added to children but the exception is still raised on line 906 :

reference.PropertyInfo.SetValue(instance, carr, null);

Coordinator
Oct 18, 2012 at 10:51 PM

The SimpleReferenceTest in the SQLite project works, so there's got to be something slightly different in your setup.  Can you post or send me the full entity definitions you're using (just the two entities in the relationship)?  I want to be certain I'm working with the same data.

Oct 19, 2012 at 7:44 AM

Hi, 

Thanks for the quick answer.

Where can I find this SimpleReferenceTest ? The only Test project using reference between 2 entities is the "ORM_1.0.12242_SRC\Tests\OpenNETCF.ORM.Test" but it is using SqlCe. I already tried to modify this project to use SQLite replacing SqlCe references and some code to initialize the store, and I got the same problem with the select on the Author table referencing Book. It would be great to have a similar project with SQLite that work with you.

Here is my 2 Entities :

Positions.cs

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using OpenNETCF.ORM;

namespace NEXCAPUP_PDA.main.src.business.model
{
    [Entity(KeyScheme = KeyScheme.Identity)]
    public class Position : IEquatable
    {
        public Position() {            
        }

        [Field(IsPrimaryKey = true)]
        public int positionId { get; set; }

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

        [Reference(typeof(Location), "positionId")]
        public Location[] locations { get; set; }

        public bool Equals(Position other) {
            return this.positionId == other.positionId;
        }
    }
}

Location.cs
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using OpenNETCF.ORM;

namespace NEXCAPUP_PDA.main.src.business.model
{
    [Entity(KeyScheme = KeyScheme.Identity)]
    public class Location : IEquatable
    {
        public Location() {
            // this is required for cascading inserts to work
            locationId = -1;
        }

        [Field(IsPrimaryKey = true)]
        public int locationId { get; set; }

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

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

        public bool Equals(Location other)
        {
            return this.locationId == other.locationId;
        }
    }
}

Coordinator
Oct 22, 2012 at 3:11 PM

I think I need you to send me a full repro app.  I tested with my entities and your.  I tested on the desktop and a WinMo device, and all of them work just fine.  Here's an example of working code:

public bool DoReferentialInserts()
{
    try
    {
        Store.AddType<Author>();
        Store.AddType<Book>();
        Store.CreateOrUpdateStore();

        // insert an author
        var dumas = new Author() { Name = "Alexadre Dumas" };
        Store.Insert(dumas);

        // insert a couple books.
        // note that we're inserting the foreign key value
        Store.Insert(
            new Book()
            {
                AuthorID = dumas.ID,
                Title = "The Count of Monte Cristo"
            });

        Store.Insert(
            new Book()
            {
                AuthorID = dumas.ID,
                Title = "The Three Musketeers"
            });

        // now get the authors back, telling ORM to fill the references
        var authors = Store.Select<Author>(true).ToArray();

        if (authors.Length != 1) return false;
        if (authors[0].Books.Length != 2) return false;

        return true;
    }
    catch(Exception ex)
    {
        return false;
    }
}

Oct 23, 2012 at 5:42 AM

Hi,

I've got exactly the same problem and I've been going around and around in ever decreasing circles for acouple fo days now!

My entities look much the same as the first set above from linkjuice, and I've got the same with the insert() working OK, but not the select().

One change I have made to the ORM ReferenceAttribute is to add in the FK name for the child object. I was finding that it wasn't selecting the right field to get the down-line object for the SQL query. I'm reasonably comfortable that this isn't causing the issue, as I'm getting the Exception in the same place as lnkjuice.

What is a good email address to send you the sample app I'm working on?

Your help would be much appreciated!

Many thanks,
Mike

Coordinator
Oct 23, 2012 at 12:54 PM

So I don't have to post my email and get flooded with spam, just click my name to the left and send me a message.  I'll reply with my actual email address.

Coordinator
Oct 23, 2012 at 8:21 PM

Are you running with the *latest* code?  Not the latest Release, but the latest code under source control (http://orm.codeplex.com/SourceControl/list/changesets)? 

Dec 21, 2012 at 8:02 PM

Hello

I am experiencing the same problem when attempting to select entities with references populated.  Inserting and selecting without populating references works fine.  Earlier today I downloaded the latest source code (100805) which did not help.  I have not stepped through this build's source, however, I did step through the release version's source.  The error occurs in OpenNETCF.ORM.CF\SQL Store Base\SQLStoreBase.cs around line 1021:

if (reference.PropertyInfo.PropertyType.IsArray)
{
       reference.PropertyInfo.SetValue(instance, carr, null);
//     reference.PropertyInfo.SetValue(instance, Convert.ChangeType(carr, reference.PropertyInfo.PropertyType), null);
}

I am deploying to a Windows Mobile 6 Pro emulator and am using SqlCe.  I am also using OpenNETCF IoC.

Thanks

Coordinator
Dec 21, 2012 at 8:50 PM

Is this with the sample entities, or something different?  I need to be able to repro the failure to fix it.

Dec 21, 2012 at 9:29 PM

That was unexpectedly fast...

I ran the sample tests and did not get the error so obviously it's something in my code/setup.

I created some very simple entities to test within my app.  They work...

    [Entity(KeyScheme=KeyScheme.Identity)]
    public class Parent
    {
        [Field(IsPrimaryKey = true)]
        public int ParentID { get; set; }

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

        [Reference(typeof(Child), "ParentID")]
        public Child[] Children { get; set; }
    }

And...

    [Entity(KeyScheme=KeyScheme.Identity)]
    public class Child
    {
        [Field(IsPrimaryKey = true)]
        public int ChildID { get; set; }

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

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

    }

Now for the more complicated classes...

    [Entity(KeyScheme=KeyScheme.GUID)]
    public class Trip : BaseEntity
    {
        public Trip()
        {
            Stops = null;
        }

        [Field(IsPrimaryKey=true)]
        public Guid TripID
        {
            get { return ID; }
            set { ID = value; }
        }

        [Field]
        public Guid ManagerID { get; set; }

        [Field]
        public Guid AssignedToID { get; set; }

        [Field]
        public DateTime? AssignedTime { get; set; }

        [Field]
        public Guid TripStatusID { get; set; }

        [Field]
        public DateTime? StartTime { get; set; }

        [Field]
        public DateTime? EndTime { get; set; }

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

        [Reference(typeof(Stop), "TripID", Autofill=false)]
        public List<Stop> Stops { get; set; }

        public int StopCount
        {
            get
            {
                if (Stops == null)
                    return 0;
                else
                    return Stops.Count;
            }
        }
    }

And...

    [Entity(KeyScheme=KeyScheme.GUID)]
    public class Stop
    {
        [Field(IsPrimaryKey = true)]
        public Guid StopID
        {
            get { return ID; }
            set { ID = value; }
        }

        [Field]
        public Guid TripID { get; set; }

        [Field]
        public Guid StopTypeID { get; set; }

        [Field]
        public Guid? OrderItemID { get; set; }

        [Field]
        public Guid? RecipientID { get; set; }

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

        [Field]
        public Guid? PickupLocationID { get; set; }

        [Field]
        public Guid StopStatusID { get; set; }

        [Field]
        public Guid? RouteID { get; set; }

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

        public Guid ID { get; set; }

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

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

        [Field]
        public DateTime ChangeStamp { get; set; }
    }
The simple classes, Parent/Child, worked as expected when retrieving the parent with children.  The more complex classes throw the ArgumentException when populating with references.  I executed the Parent/Child retrieval just before the code that executes the Trip/Stop retrieval.  This leads me to believe the problem has something to do with a property/attribute on either the Trip or Stop entity.

Coordinator
Dec 21, 2012 at 9:31 PM

Alright, I'll take a look at it though with the weekend and holiday it will likely be next week before I get to it.

Dec 21, 2012 at 10:00 PM
Much appreciated...have a good holiday


From my Android phone on T-Mobile. The first nationwide 4G network.


-------- Original message --------
Subject: Re: store.Select<TestTable> with oneToMany relation throw ArgumentException [orm:399864]
From: ctacke <notifications@codeplex.com>
To: [email removed]
CC:


From: ctacke

Alright, I'll take a look at it though with the weekend and holiday it will likely be next week before I get to it.

Jan 7, 2013 at 2:16 PM

Any luck yet?