Seek/SetRange requires that you specify table index on the SqlCeCommand instance...

Dec 5, 2012 at 6:50 PM

Greetings all:

An ORM noob here with hopefully a simple question.  Given a one-to-many relationship between two tables Order and OrderDetails defined as

[Entity(KeyScheme = KeyScheme.Identity)]
public partial class Order : PersistedEntity
{
	[Field(IsPrimaryKey = true, AllowsNulls = false, SearchOrder=FieldSearchOrder.Ascending)]
	public virtual Int32 OrderID { get; set; }
	public override Int32 ID { get { return OrderID; } set { } }

	[Field(AllowsNulls = false, RequireUniqueValue = false, DataType = System.Data.DbType.Int32, SearchOrder = FieldSearchOrder.Ascending)]
	public virtual System.Nullable<Int32> OrderDetailID { get; set; }

	[Reference(typeof(OrderDetail), "OrderDetailID", Autofill = true, ReferenceType = ReferenceType.ManyToOne)]
	public virtual OrderDetail OrderDetail { get; set; }

	// omitted several remaining properties for brevity
}	

public partial class OrderDetail : PersistedEntity
{
	[Field(IsPrimaryKey = true, AllowsNulls = false, SearchOrder=FieldSearchOrder.Ascending)]
	public virtual Int32 OrderDetailID { get; set; }
	public override Int32 ID { get { return OrderDetailID; } set { } }
	
	[Field(AllowsNulls = false, RequireUniqueValue=true, Length = 100, SearchOrder = FieldSearchOrder.Ascending)]
	public virtual String Name { get; set; }
	
	// omitted several remaining properties for brevity
}	

I was thinking I could get my OrderDetail object in my Order object populated with a simple call like so. 

Order od = GetByID(1);  // where 1 denotes the OrderID

Unfortunately, I get the message: "Seek/SetRange requires that you specify table index on the SqlCeCommand instance before calling those methods"

My GetByID function looks like this

public virtual T GetByID(int id)
{
	if (id <= 0) { throw new ArgumentOutOfRangeException("id"); }
	
	/* The next line of code puts out this messsage:
		throws System.InvalidOperationException was unhandled by user code Message=Seek/SetRange requires that 
		you specify table index on the SqlCeCommand instance before calling those methods.
	*/
	T fromDb = DataStore.Select<T>(id, true);	
  
	//T fromDb = DataStore.Select<T>(id, false);  lazy retrieval works fine
	return fromDb;
}

Each time I run this program I create a new database and seed it with test values.  I'm running version 1.0.12047.0.  My stack trace dump follows:

System.InvalidOperationException was unhandled by user code
  Message=Seek/SetRange requires that you specify table index on the SqlCeCommand instance before calling those methods.
  Source=System.Data.SqlServerCe
  StackTrace:
       at System.Data.SqlServerCe.SqlCeDataReader.Seek(DbSeekOptions dbSeekOptions, Object[] index)
       at OpenNETCF.ORM.SqlCeDataStore.Select(Type objectType, IEnumerable`1 filters, Int32 fetchCount, Int32 firstRowOffset, Boolean fillReferences)
       at OpenNETCF.ORM.SQLStoreBase`1.Select(Type objectType, String searchFieldName, Object matchValue, Int32 fetchCount, Int32 firstRowOffset, Boolean fillReferences)
       at OpenNETCF.ORM.SQLStoreBase`1.Select(Type objectType, String searchFieldName, Object matchValue, Int32 fetchCount, Int32 firstRowOffset)
       at OpenNETCF.ORM.SQLStoreBase`1.FillReferences(Object instance, Object keyValue, ReferenceAttribute[] fieldsToFill, Boolean cacheReferenceTable)
       at OpenNETCF.ORM.SqlCeDataStore.Select(Type objectType, IEnumerable`1 filters, Int32 fetchCount, Int32 firstRowOffset, Boolean fillReferences)
       at OpenNETCF.ORM.SQLStoreBase`1.Select(Type objectType, String searchFieldName, Object matchValue, Int32 fetchCount, Int32 firstRowOffset, Boolean fillReferences)
       at OpenNETCF.ORM.SQLStoreBase`1.Select[T](Object primaryKey, Boolean fillReferences)
       at Stark.AC.DataAccess.DAL.BaseDAL`1.GetByID(Int32 id) in
	   <removed>Removed because of proprietary restrictions</removed>
  InnerException: 

With lazy loading, I can get the properties of my Order object populated with data.  However, I need to get the OrderDetails object populated too.  Can anyone point me in the right direction here?  Thanks!

Coordinator
Dec 6, 2012 at 3:47 PM

Can you send me a database and code files for the entities?  I can test them out and find the bug (it smells like a bug to me).

Dec 6, 2012 at 10:04 PM

Chris:

Thanks for your quick reply!  Unfortunately, I'm restricted with disclosing any software.  However, I have more information to report to you about.  Using your source code, I can now reproduce and work around the error.

I see you have a dictionary where the primary key index names are stored.  This dictionary accumulates its values as it encounters new table/entities.  At program start up, calling DataStore.Select() on my OrderDetail table followed by a DataStore.Select on my Order table works without issue.

Conversely, switching the sequence of DataStore.Select calls produces the crash in my initial post.  At program start up, calling DataStore.Select() on my Order table prior to a Data.Select() call on the OrderDetail table fails because the primary key index name is not present in the m_entities...PrimaryKeyIndexName property.

If the method CheckPrimaryKeyIndex() could be called as the Entities collection is being populated, I think this issue could be resolved.  Not sure what the drawbacks would be.  Anyway, thanks for a very helpful project!

Regards,

ken