Identity columns and saving new entity hierarchies

Posts   
 
    
Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 27-Aug-2007 18:57:47   

In the documentation it shows how to prefech entities and their related entities. I also understand that the adapter can save entity trees by setting recurse to true. However is it possible to save an entity tree when the primary entity has not been persisted and the primary key of the primary entity is generated by the database (identity column).

Party

(PK) PartyId (int) --identity--

PartyRole

(PK) PartyId (int) FK - to Party>PartyId (PK) RoleId

Can I create a new party entity (p) and add a new partyroleentity to the p.partyrole collection and persist the data to the database with out the "you can not input a null partyid into the partyrole table" message? Or do I have to persist the partyentity first, get the new id and assign it to the partyrole entity and then save that entity?

Thanks

Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 27-Aug-2007 19:02:44   

Just after writing the post I saw the answer in another post which answers the identity problem. Now, how can this be done with a guid as a primary key instead of an int. I would like to use sqls newsequentialid() function for creating an guid instead of creating it client side. Will recurse work in this senario?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 28-Aug-2007 11:19:59   

Brandt wrote:

Just after writing the post I saw the answer in another post which answers the identity problem. Now, how can this be done with a guid as a primary key instead of an int. I would like to use sqls newsequentialid() function for creating an guid instead of creating it client side. Will recurse work in this senario?

Yes. Just define your pk field in the database with a default function: NEWSEQUENTIALID(). Then you simply recurse the save and LLBLGen Pro will notice this and will generate SQL to obtain the new ID, set the PK to that value and sync FK fields with that value.

Frans Bouma | Lead developer LLBLGen Pro
Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 28-Aug-2007 12:32:08   

Otis wrote:

Brandt wrote:

Just after writing the post I saw the answer in another post which answers the identity problem. Now, how can this be done with a guid as a primary key instead of an int. I would like to use sqls newsequentialid() function for creating an guid instead of creating it client side. Will recurse work in this senario?

Yes. Just define your pk field in the database with a default function: NEWSEQUENTIALID(). Then you simply recurse the save and LLBLGen Pro will notice this and will generate SQL to obtain the new ID, set the PK to that value and sync FK fields with that value.

I'll try that again. For some reason it was giving me the error but I can't remember if i set the refetch to true or not.

Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 09-Oct-2007 02:50:46   

Brandt wrote:

Otis wrote:

Brandt wrote:

Just after writing the post I saw the answer in another post which answers the identity problem. Now, how can this be done with a guid as a primary key instead of an int. I would like to use sqls newsequentialid() function for creating an guid instead of creating it client side. Will recurse work in this senario?

Yes. Just define your pk field in the database with a default function: NEWSEQUENTIALID(). Then you simply recurse the save and LLBLGen Pro will notice this and will generate SQL to obtain the new ID, set the PK to that value and sync FK fields with that value.

I'll try that again. For some reason it was giving me the error but I can't remember if i set the refetch to true or not.

Actually I am still getting an error when trying to save an entity and its related entities using primary keys that are guid's created by newsequentialid() using the 2.5.07.1005 build. Everytime I try to save an entity and its child entites using refetch and recurse it throws a {"The given key was not present in the dictionary."} error. Here is the code that saves the entity, the stack trace and the sql that is sent to the database. Whats weird is that the refetch trys to refetch a networkdevice where the networkdeviceguid is NULL.

NetworkDeviceEntity _netest = new NetworkDeviceEntity();
                    _netest.Name = "TestDevice1";
                    _netest.DomainName = "corp.halliburton.com";
                    _netest.SiteId = "HOU-ALF";
                    _netest.Status = "Production";
                    _netest.AssetTag = "";
                    _netest.SerialNumber = "";
                    _netest.CreatedBy = "Brandt Beal";
                    _netest.CreatedOn = DateTime.Now;
                    _netest.UpdatedBy = "Brandt Beal";
                    _netest.UpdatedOn = DateTime.Now;
                    NetworkDeviceAttributeEntity _attrib = _netest.NetworkDeviceAttribute.AddNew();
                    _attrib.Name = "t1";
                    _attrib.Value = "t2";
                    _attrib.AttributeGroup = "General";
using (DataAccessAdapter _adapter = new DataAccessAdapter())
            {
                return _adapter.SaveEntity(_netest, true,true);
            }

Stack Trace :


   at System.ThrowHelper.ThrowKeyNotFoundException()
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at SD.LLBLGen.Pro.ORMSupportClasses.DynamicQueryEngineBase.CreateInsertDQ(IEntityFieldCore[] fields, IFieldPersistenceInfo[] fieldsPersistenceInfo, IDbConnection connectionToUse)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.CreateInsertDQ(IEntity2 entityToSave, IFieldPersistenceInfo[] persistenceInfoObjects)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.PersistQueue(List`1 queueToPersist, Boolean insertActions, Int32& totalAmountSaved)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.SaveEntity(IEntity2 entityToSave, Boolean refetchAfterSave, IPredicateExpression updateRestriction, Boolean recurse)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.SaveEntity(IEntity2 entityToSave, Boolean refetchAfterSave, Boolean recurse)
   at InfrastructureCentral.BLServices.NetworkDeviceService.SaveNetworkDevice(NetworkDeviceEntity entity, Boolean refetch, Boolean recurse) in C:\Users\hbb9745\Documents\Visual Studio 2005\Projects\InfrastructureCentral\Source\DataServices\InfrastructureCentral.BLServices\NetworkDeviceService.cs:line 291
   at InfrastructureCentral.NetworkDevices.Views.CopyDevicePresenter.OnCopyNetworkDevice() in C:\Users\hbb9745\Documents\Visual Studio 2005\Projects\InfrastructureCentral\Source\Modules\NetworkDevices\Views\CopyDevice\CopyDevicePresenter.cs:line 176

SQL Called :



[INSERT]

exec sp_executesql N'INSERT INTO [ICDEV].[Infrastructure].[NetworkDevice] ([Name], [DomainName], [Status], [SiteId], [AssetTag], [SerialNumber], [CreatedOn], [CreatedBy], [UpdatedOn], [UpdatedBy])  VALUES (@Name, @DomainName, @Status, @SiteId, @AssetTag, @SerialNumber, @CreatedOn, @CreatedBy, @UpdatedOn, @UpdatedBy)',N'@Name nvarchar(50),@DomainName varchar(100),@Status varchar(25),@SiteId varchar(30),@AssetTag varchar(50),@SerialNumber varchar(75),@CreatedOn smalldatetime,@CreatedBy varchar(100),@UpdatedOn smalldatetime,@UpdatedBy varchar(100)',@Name=N'TestDevice1',@DomainName='corp.halliburton.com',@Status='Production', @SiteId='HOU-ALF',@AssetTag='',@SerialNumber='',@CreatedOn='2007-10-08 19:29:00:000',@CreatedBy='Brandt Beal',@UpdatedOn='2007-10-08 19:29:00:000',@UpdatedBy='Brandt Beal'

[SELECT]

SELECT [ICDEV].[Infrastructure].[NetworkDevice].[NetworkDeviceGuid], [ICDEV].[Infrastructure].[NetworkDevice].[Name], [ICDEV].[Infrastructure].[NetworkDevice].[DomainName], [ICDEV].[Infrastructure].[NetworkDevice].[Class], [ICDEV].[Infrastructure].[NetworkDevice].[Status], [ICDEV].[Infrastructure].[NetworkDevice].[SiteId], [ICDEV].[Infrastructure].[NetworkDevice].[Project], [ICDEV].[Infrastructure].[NetworkDevice].[Critical], [ICDEV].[Infrastructure].[NetworkDevice].[Monitored], [ICDEV].[Infrastructure].[NetworkDevice].[Description], [ICDEV].[Infrastructure].[NetworkDevice].[Location], [ICDEV].[Infrastructure].[NetworkDevice].[SupportLevelId], [ICDEV].[Infrastructure].[NetworkDevice].[AssetTag], [ICDEV].[Infrastructure].[NetworkDevice].[SerialNumber], [ICDEV].[Infrastructure].[NetworkDevice].[Manufacture], [ICDEV].[Infrastructure].[NetworkDevice].[Model], [ICDEV].[Infrastructure].[NetworkDevice].[WarrantyStartDate], [ICDEV].[Infrastructure].[NetworkDevice].[WarrantyEndDate], [ICDEV].[Infrastructure].[NetworkDevice].[Decommissioned], [ICDEV].[Infrastructure].[NetworkDevice].[CreatedOn], [ICDEV].[Infrastructure].[NetworkDevice].[CreatedBy], [ICDEV].[Infrastructure].[NetworkDevice].[UpdatedOn], [ICDEV].[Infrastructure].[NetworkDevice].[UpdatedBy] FROM [ICDEV].[Infrastructure].[NetworkDevice]  WHERE ( ( [ICDEV].[Infrastructure].[NetworkDevice].[NetworkDeviceGuid] IS NULL))


Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 09-Oct-2007 03:25:12   

Never Mind ----------------->>>>>>>>>>>>>

<add key="SqlServerDQECompatibilityLevel" value="2" /> <!-- 0=SqlServer7 1=SqlServer2000 2=SqlServer2005 -->

ARG! ARG! ARG! ARG!

[ Otis ] - Would it be possible to add the option to set the default for SqlServerDQECompatibilityLevel in the designer either when when selecting the templates or as a project default. I would want the adapter hard coded to default to that level if a key wasn't found in the app.config instead of defaulting to the lowest compatability level.

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 09-Oct-2007 10:56:03   

Would it be possible to add the option to set the default for SqlServerDQECompatibilityLevel in the designer either when when selecting the templates or as a project default. I would want the adapter hard coded to default to that level if a key wasn't found in the app.config instead of defaulting to the lowest compatability level.

I'm not sure if this would be the best thing to do. As SQL Server 2005 can be backward compatible, but older versions can't be forward compatible, plus SQL Server 2000 is more adopted, I guess. So IMHO, having SqlServerDQECompatibilityLevel defaults to 2005, would caue more issues.

Anyway I'll tell Frans about your request.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 09-Oct-2007 11:04:53   

The default is indeed set to sqlserver 2000 because it's considered the widest audience and sql produced for that is also working on 2005, unless you use specific features for 2005, though it's then required to set the compatibility level, which is a small thing, but if forgotten it can be causing unexpected behavior.

I'll take this into account for v3.

Frans Bouma | Lead developer LLBLGen Pro
Brandt
User
Posts: 142
Joined: 04-Apr-2007
# Posted on: 09-Oct-2007 13:51:03   

Otis wrote:

The default is indeed set to sqlserver 2000 because it's considered the widest audience and sql produced for that is also working on 2005, unless you use specific features for 2005, though it's then required to set the compatibility level, which is a small thing, but if forgotten it can be causing unexpected behavior.

I'll take this into account for v3.

What I was hinting upon was in the Designer defaults we could make a selection to have the generated code default to a specific version of sql instead of having it always default to sql 2000. You would still be able to override the selection in the webconfig. Or have a template that sets the default to 2005 when it is added.