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

Disconnected API - Primary Key

10 Answers 176 Views
Development (API, general questions)
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
devoas
Top achievements
Rank 1
devoas asked on 16 Dec 2009, 10:59 AM
HI,

I have master and detail table and its been defined as managed collection thru forward mapping. When I directly Save thru Object Scope, the master.pkfield automatically populated in Detail table on save. But if I use ObjectContainer and transfer new objects to Database thru CopyTo, on scope.commit I get exception that

Insert of '1400736671-' failed: Telerik.OpenAccess.RT.sql.SQLException: Cannot insert the value NULL into column 'TranNumb', table 'mydata.dbo.SalesDetail'; column does not allow nulls. INSERT fails.
The statement has been terminated.
   at Telerik.OpenAccess.RT.Adonet2Generic.Impl.PreparedStatementImp.execute()
   at OpenAccessRuntime.Relational.conn.PooledPreparedStatement.execute()

I used following Code.

oc.CopyTo(scope,

ObjectContainer.Verify.All);

 


Please guide what is missing.

Thanks.




10 Answers, 1 is accepted

Sort by
0
devoas
Top achievements
Rank 1
answered on 19 Dec 2009, 12:16 PM
Hi,

I will be really thankful if anyone can reply on my following post regarding CopyTo method of Object Container not Transfering the Master Table's  Primary key in Detail Table......

Thanks....
0
Damyan Bogoev
Telerik team
answered on 19 Dec 2009, 06:12 PM
Hello devoas,

The problem arises when the AUTOINC identity generator is used. As the object container is not connected to the database, it is not able to obtain the id from there. You could avoid the problem by using the HIGHLOW key generator instead.
Hope that helps.

All the best,
Damyan Bogoev
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
0
devoas
Top achievements
Rank 1
answered on 20 Dec 2009, 10:19 AM
Thanks for your reply.

Please note In my current scenario I am not Creating new Master Table Record, rather Master table record already saved and it already have Primary key (TranNumb), Now I am adding new Detail Table Record. In this case it should only transfer the Master Table saved primary key to Detail table (as managed collection do) which does not required database connection as Object container already have Master Table Object... Kindly confirm why it is not automatically transferring...

Thanks.





0
devoas
Top achievements
Rank 1
answered on 23 Dec 2009, 05:51 AM

I have also tested on Highlow and still having same problem as explained in my last post that problem is not related to keygeneration rather is about transfering master table Primary key to Child Table. Now Even I tried to put the value of Primary in Detail table manually still getting error. Following is the code, please advise

            sm = persistenceService<SalesMater>.GetByPrimayKey(1);  

 


            ObjectContainer
oc;

 

            oc =

new ObjectContainer();

 

             
             IObjectCollector collector = new FetchGroupCollector(FetchGroupCollector.DeepFetchGroup);  
            oc.CopyFrom(scope,sm.GetType().Name,sm,collector);  

                oc.Transaction.Begin();  
                
                IList ilist = oc.NamedList(sm.GetType().Name);  
                sm  = (SalesMaster)ilist[0];  
 
 
 
 
            sm.CustomerId = 2;  
 
           SalesDetail sd = new SalesDetail();  
           sd.ProductId = 1;  
           sd.Qty = 1500;  
           sd.Rate = 2000;  
           sd.TranNumb = sm.TranNumb;   //If I dont write this line, it is giving error Cannot insert the value NULL into column 'TranNumb'
           sm.SalesDetails.Add(sd);  
 
 
           oc.Transaction.Commit();  
           scope.Transaction.Begin();  
                oc.CopyTo(scope, ObjectContainer.Verify.All);    //error here after adding line sd.TranNumb = sm.TranNumb;
           scope.Transaction.Commit();  
 
 
 
 

Error Message :

Telerik.OpenAccess.OpenAccessException was caught
  Message="Unable to cast object of type 'Telerik.OpenAccess.RT.CopySM' to type 'DALTest.SalesMaster'."
  Source="Telerik.OpenAccess"
  CanRetry=false
  StackTrace:
       at Telerik.OpenAccess.SPI.Backends.ThrowException(Exception e)
       at Telerik.OpenAccess.RT.ExceptionWrapper.Throw()
       at OpenAccessRuntime.DataObjects.PCStateMan.handleException(Exception x)
       at OpenAccessRuntime.DataObjects.PCStateMan.setIntField(PersistenceCapable _pc, Int32 field, Int32 currentValue, Int32 newValue)
       at Telerik.OpenAccess.RT.CopySM.replacingIntField(PersistenceCapable pc, Int32 field)
       at DALTest.SalesDetail.OpenAccessEnhancedReplaceField(Int32 )
       at Telerik.OpenAccess.RT.CopySM.CopyTo(PersistenceCapable pc, Object[] _data, ObjectRepositoryMerger _m, StateManager onlineSm, Int32[] managedFields)
       at Telerik.OpenAccess.RT.DisconnectedStateManager.Telerik.OpenAccess.SPI.OfflineStateManager.FillNewObject(PersistenceCapable pc, ObjectRepositoryMerger mrg, StateManager onlineSm)
       at OpenAccessRuntime.DataObjects.PMProxy.updateFromCopy(PersistenceCapable pc, OfflineStateManager cpy, ObjectRepositoryMerger merger, Boolean isNew)
       at Telerik.OpenAccess.RT.ContainerMerger.UpdateDestinationObject(ObjectMergeInfo info)
       at Telerik.OpenAccess.RT.ObjectMerger.CopyObjectContent(ObjectMergeInfo info, IObjectMergerContext ctx)
       at Telerik.OpenAccess.RT.ObjectMerger.UpdateObject(ObjectMergeInfo info, IObjectMergerContext ctx)
       at Telerik.OpenAccess.RT.ContainerMerger.MergeList(ArrayList infos, Boolean avoidLoading, Boolean copyNew)
       at Telerik.OpenAccess.RT.ContainerMerger.MergeAllNewChangedDeletedCleanHollow(Boolean forceResolve, ArrayList changes)
       at Telerik.OpenAccess.RT.ContainerMerger.MergeAll(ArrayList changes)
       at Telerik.OpenAccess.RT.ContainerMerger.Merge(ObjectContainer from, IObjectScope to, Hashtable conflicts, Exception e, ArrayList changes)
       at Telerik.OpenAccess.ObjectContainer.CopyTo(IObjectScope objectScope, Verify verifyMode, ContainerMerger merger, ArrayList InternalChgSet)
       at Telerik.OpenAccess.ObjectContainer.CopyTo(IObjectScope objectScope, Verify verifyMode, Boolean allFields)
       at Telerik.OpenAccess.ObjectContainer.CopyTo(IObjectScope objectScope, Verify verifyMode)
       at Data.Test`1.Save() in F:\TelerikTest\DataTest.cs:line 329
  InnerException: System.InvalidCastException
       Message="Unable to cast object of type 'Telerik.OpenAccess.RT.CopySM' to type 'DALTest.SalesMaster'."
       Source="DALTest"
       StackTrace:
            at DALTest.SalesDetail.OpenAccessEnhancedReplaceField(Int32 )
            at OpenAccessRuntime.DataObjects.PCStateMan.doRead(FieldMetaData fmd, Object oldValue)
            at OpenAccessRuntime.DataObjects.PCStateMan.getObjectFieldImp(PersistenceCapable pc, FieldMetaData fmd, Object currentValue)
       InnerException:

0
Damyan Bogoev
Telerik team
answered on 23 Dec 2009, 04:24 PM
Hi devoas,

To achieve this you should do the following changes to the provided example:
1.    The IObjectScope instance should be the same as the one that the 'sm' object lives in. To obtain it, use the following code:

sm = persistenceService<SalesMater>.GetByPrimayKey(1);  
scope = Database.GetContext(sm) as IObjectScope;

2.    When you retrieve the 'sm' object from the ObjectContainer's named list you should use the GetObjectById method:

sm = oc.GetObjectById(Database.OID.ParseObjectId(typeof(Order), 1)) as SalesMaster;

3.    Change the SalesDetails to unmanaged collection. Otherwise you would get a “Change of identity is not supported.” exception.

Now you could modify the SalesMaster record and insert a new SalesDetail.
Hope that helps.

Best wishes,
Damyan Bogoev
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
0
devoas
Top achievements
Rank 1
answered on 23 Dec 2009, 10:37 PM
Thanks alot for the help and its working by changing the collection to unmanaged.. Does this means ObjectContainer  not supporting Managed Collection..... ?

But by doing so I am also having problem when New SalesMaster Record is created and its child (salesDetail) added, then when I will get and Update the Master tables primary key to child object (salesdetail)..... I want to avoid this and would like to use manage collection, is there any other way.... or is it possible to set the collection handling type at runtime to either managed or unmanaged. ?

Thanks.

 

0
devoas
Top achievements
Rank 1
answered on 26 Dec 2009, 08:42 AM
Hi Damyan Bogoev

I found that same code is working when I just set the Parent Object in child instead of foreign key. Like

 sd.salesMaster = sm;

Its working without any error and transfer Master table  Primary key in detail table. But resultant Record is showing one more issue.
that ProductID is Null .... even I set  sd.ProductId = 1;  

using same solution to link the Product Object to SalesDetail.Product I did following

 

 

   
 
    IObjectId oid = Database.OID.ParseObjectId(typeof(Product), sd.ProductId.ToString());   
 
    sd.Product  = (Product)(Database.GetContext(bll.Current)).GetObjectById(oid);  
 
 

and It Saved.....

 

  • Does this mean Object Container cannot translate foreign Key and need to set the Parent objects manually ?

 

  • In above case if I use ProductId = 2, which was not loaded in Object Container (thru Salesmaster - Deepfetch...)  then it save null in ProductId ..... Kindly guide how can this work.....  Is there any way in Object Container, that it can fill the missing object that are refered automatically.....


Thanks    

 





0
Zoran
Telerik team
answered on 29 Dec 2009, 08:28 AM
Hello devoas,

It seems that your issue comes from the fact that the desired product was not loaded in the object container.
The object container can resolve only those references to the objects that it was filled with. It can not resolve references to objects that are not part of the container as the container is designed for work in disconnected scenarios. That means that the container does not have direct access to the database for finding the missing records.

The code you have sent is not necessary actually as it assigns the product object which is resolved by the corresponding productId that is already assigned to the salesDetail object. If the product object existed, it would have been automatically resolved by OpenAccess since the id is already assigned to the salesDetail object.

All the best,
Zoran
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
0
devoas
Top achievements
Rank 1
answered on 29 Dec 2009, 09:59 AM
Hi Zoran,

Thanks alot for your reply.

As you said that the object container can resolve only those references to the objects that it was filled with. But I cannot see this working as I need to set the reference manually. Following are the summarize issues from my post .

1. Managed collections are not handled in Object Container and need to set references manually, where as these are working properly under scope. (Master/Detail : Primary keys)

2. Even if the primary key / Id is set in any object, it does not work till the reference object is set. 
 sd.TranNumb = sm.TranNumb;   // this is not working and at the time of saving sd.TranNumb throw Null Value Error.
      sd.ProductId = 1;           // this is also not working and saved Null in productID in Database

  Its working after following kind of code (manually setting the Object instead of foreign key)

    sd.salesMaster = sm;
    

3. Regarding Unloaded Objects in Object Container ,  I understand the disconnected mechanism but there is any possibility that before using CopyTo --> Scope (Saving Actual Data) where Database/scope exist,  Open Access can set all references and Data should be updated properly. As the Unloaded Data is only used in references to other objects and their Primary key / Ids values are already provided....  


Basically we are trying to use Object container to Transfer Persistence Objects to UI and then UI fills and return to business logic, which validates and Save.  Otherwise it is required to enable Scop.Transaction.Begin from the Point Object is send to UI to allow changes in binded objects. But above issues restricting flexible handling. Please suggest  best practice  with minimum code writing and take full advantage of ORM.

Thanks,
devoas
 


0
Zoran
Telerik team
answered on 04 Jan 2010, 05:18 PM
Hi devoas,

Working with managed collections in disconnected scenario is possible, but unlike in the connected one, you should mark the desired collection with the [ManagedInverse] attribute. Regarding the resolving of the foreign key references, this seems like a bug in the container when it copies the data back to the database and we will make sure that it is fixed in one of our future releases.

Nevertheless, if you have a web application scenario, I think your architecture should be scope based e.g. you should work in a connected fashion. Is there any specific reason why are you using the object container? It is originally designed for transporting persistent objects or serializing them in a disconnected location.

All the best,
Zoran
the Telerik team

Instantly find answers to your questions on the new Telerik Support Portal.
Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Tags
Development (API, general questions)
Asked by
devoas
Top achievements
Rank 1
Answers by
devoas
Top achievements
Rank 1
Damyan Bogoev
Telerik team
Zoran
Telerik team
Share this question
or