Copy entity graph

Posts   
 
    
tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 25-Sep-2007 01:43:34   

.NET: 1.1 Yes, I know we need to upgrade. LLBLGen Version: 2.0 Runtime: v1.1.4322

I'm trying to write a method to copy a entity graph to create new model year products. I have read a number of other threads about this subject and between them all have come up with my own code to make this work in my case. Now the problem is that everything I see and can debug in code looks correct but the graph isn't being saved to the database correctly.

I have three tables involved in this and they are related like so:

Product <-- ProductVersion <-- Stem --> Product

That might look a little odd because the Stem sits between the Product and ProductVersion but it's worked the I wanted even though it may not be needed.

Here is the method that doesn't work.


/// <summary>
/// Duplicates an entity in the database. Primarily used for creating a new model product from a previous years product.
/// </summary>
/// <param name="product"></param>
public ProductEntity DuplicateProduct(ProductEntity product)
{
    ProductEntity newProduct = new ProductEntity();
    string productTypeName = product.ProductType.TypeName;

    // Iterate over the fields to copy.
    foreach(EntityField2 field in product.Fields)
    {
        string fieldName = field.Name;

        // Skip the ID fields so that LLBLGen runtime re-creates the ID's.
        if ( field.IsPrimaryKey )
            continue;

        object currentFieldValue = product.Fields[fieldName].CurrentValue;

        // Fields in unique constraints must have their values customized or the entity won't save.
        switch(fieldName)
        {
            case "ActiveState":
                currentFieldValue = "NEW";
                break;
            case "ModelYear":
                currentFieldValue = Convert.ToString(DateTime.Now.Year + 1);
                break;
        }

        // Copy the field values.
        newProduct.Fields[fieldName].CurrentValue = currentFieldValue;
    }

    foreach(ProductVersionEntity productVersion in product.ProductVersion)
    {
        ProductVersionEntity newProductVersion = new ProductVersionEntity();

        // Iterate over the fields to copy.
        foreach(EntityField2 field in productVersion.Fields)
        {
            string fieldName = field.Name;

            // Skip the ID fields so that LLBLGen runtime re-creates the ID's.
            if ( fieldName == "ProductVersionID" || fieldName == "ProductID" )
                continue;

            object currentFieldValue = productVersion.Fields[fieldName].CurrentValue;
            
            // Fields in unique constraints must have their values customized or the entity won't save.
            switch(fieldName)
            {
                case "ActiveState":
                    currentFieldValue = "NEW";
                    break;
                case "DistributorNumber":
                    currentFieldValue += "-new";
                    break;
                case "OECostPrice":
                    currentFieldValue = 0;
                    break;
                case "OEPrice":
                    currentFieldValue = 0;
                    break;
                case "RPCostPrice":
                    currentFieldValue = 0;
                    break;
                case "RPPrice":
                    currentFieldValue = 0;
                    break;
            }

            // Copy the field values.
            newProductVersion.Fields[fieldName].CurrentValue = currentFieldValue;
        }

        // Get an instance of the part entity to copy.
        // This would be someting like ProductVersion.Stem.
        object productVersionPart = productVersion.GetType().GetProperty(productTypeName).GetValue(productVersion, new object[0]);
        if ( productVersionPart != null )
        {
            // Cast the part instance to EntityBase2.
            EntityBase2 currentPart = (EntityBase2)productVersionPart;
            
            // Create new instance of part being copied.
            Assembly assembly = Assembly.GetAssembly(typeof(ProductEntity));
            Type partType = assembly.GetType("WrenchScience.LLBLGen.EntityClasses." + productTypeName + "Entity");
            EntityBase2 partInstance = (EntityBase2)partType.GetConstructor(new Type[0]).Invoke(new object[0]);

            // Iterate over the fields to copy.
            foreach(EntityField2 field in currentPart.Fields)
            {
                string fieldName = field.Name;
                
                // Skip the ID fields so that LLBLGen runtime re-creates the ID's.
                if ( fieldName == "ProductVersionID" || fieldName == productTypeName + "ID" )
                    continue;

                // Copy the field values.
                partInstance.Fields[fieldName].CurrentValue = field.CurrentValue;
            }

            // Set related part as dirty to force save.
            this.SetEntityDirty(partInstance);

            // Add related part to ProductVersion.
            ((EntityBase2)newProductVersion).SetRelatedEntity(partInstance, productTypeName);
        }

        // Set ProductVersion as dirty to force save.
        this.SetEntityDirty(newProductVersion);

        // Add ProductVersion to Product.ProductVersion collection.
        newProduct.ProductVersion.Add(newProductVersion);
    }

    // Set Product as dirty to force save.
    this.SetEntityDirty(newProduct);

    return newProduct;
}

There should be one insert for Product, then 11 for ProductVersion and 11 for Stem Instead there is only one for each which I don't understand. The other really odd thing about the insert for the Stem is that the Stem.ProductVersionID is the relation to the ProductVersion table and it's not even included, then the StemID (relates to Product.ProductID) is null.

Here is the insert statement.


SET TRANSACTION ISOLATION LEVEL READ COMMITTED;BEGIN TRANSACTION [RecursiveSave]
go
declare @P1 int
set @P1=5952
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[Product] ([ActiveState], [ProductTypeID], [StyleCode], [ManufacturerID], [Model], [BaseModel], [ModelYear], [Warranty], [Material], [MaterialDescription], [WeightLimit], [Discount], [FreeShipping], [SortOrder], [CreateDate], [UpdateDate], [WSNotes], [ImageName], [Advertise], [AdvertisementImage], [ProductCatagoryID], [SizingImage], [BikeDiscount])  VALUES (@ActiveState, @ProductTypeID, @StyleCode, @ManufacturerID, @Model, @BaseModel, @ModelYear, @Warranty, @Material, @MaterialDescription, @WeightLimit, @Discount, @FreeShipping, @SortOrder, @CreateDate, @UpdateDate, @WSNotes, @ImageName, @Advertise, @AdvertisementImage, @ProductCatagoryID, @SizingImage, @BikeDiscount);SELECT @ProductID=SCOPE_IDENTITY()', N'@ProductID int output,@ActiveState char(3),@ProductTypeID int,@StyleCode char(2),@ManufacturerID int,@Model varchar(50),@BaseModel varchar(50),@ModelYear char(4),@Warranty char(4),@Material varchar(36),@MaterialDescription varchar(50),@WeightLimit decimal(5,2),@Discount decimal(5,4),@FreeShipping bit,@SortOrder smallint,@CreateDate datetime,@UpdateDate datetime,@WSNotes varchar(500),@ImageName varchar(50),@Advertise bit,@AdvertisementImage varchar(50),@ProductCatagoryID int,@SizingImage varchar(50),@BikeDiscount decimal(5,4)', @ProductID = @P1 output, @ActiveState = 'NEW', @ProductTypeID = 16, @StyleCode = 'M ', @ManufacturerID = 146, @Model = 'ATAC Pro', @BaseModel = '', @ModelYear = '2008', @Warranty = '   ', @Material = 'Aluminum', @MaterialDescription = '', @WeightLimit = 500.00, @Discount = 0.0000, @FreeShipping = 0, @SortOrder = 100, @CreateDate = 'May 30 2006  4:54:57:480PM', @UpdateDate = 'Sep 24 2007  4:41:53:503PM', @WSNotes = '', @ImageName = '', @Advertise = 0, @AdvertisementImage = '', @ProductCatagoryID = NULL, @SizingImage = '', @BikeDiscount = 1.0000
select @P1
go
declare @P1 int
set @P1=21188
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[ProductVersion] ([ProductID], [ActiveState], [Religion], [DistributorID], [DistributorNumber], [ManufacturerNumber], [IsPartSpecific], [OECostPrice], [OEPrice], [RPCostPrice], [RPPrice], [BikeDiscount], [SaleDiscount], [Color], [ImageName], [MfrGrams], [WSGrams], [WSNotes])  VALUES (@ProductID, @ActiveState, @Religion, @DistributorID, @DistributorNumber, @ManufacturerNumber, @IsPartSpecific, @OECostPrice, @OEPrice, @RPCostPrice, @RPPrice, @BikeDiscount, @SaleDiscount, @Color, @ImageName, @MfrGrams, @WSGrams, @WSNotes);SELECT @ProductVersionID=SCOPE_IDENTITY()', N'@ProductVersionID int output,@ProductID int,@ActiveState char(3),@Religion char(1),@DistributorID int,@DistributorNumber varchar(30),@ManufacturerNumber varchar(40),@IsPartSpecific bit,@OECostPrice smallmoney,@OEPrice smallmoney,@RPCostPrice smallmoney,@RPPrice smallmoney,@BikeDiscount decimal(5,4),@SaleDiscount decimal(5,4),@Color varchar(30),@ImageName varchar(50),@MfrGrams decimal(7,2),@WSGrams decimal(7,2),@WSNotes varchar(200)', @ProductVersionID = @P1 output, @ProductID = 5952, @ActiveState = 'NEW', @Religion = 'B', @DistributorID = 288, @DistributorNumber = '85-2143-new', @ManufacturerNumber = '', @IsPartSpecific = 0, @OECostPrice = $0.0000, @OEPrice = $0.0000, @RPCostPrice = $0.0000, @RPPrice = $0.0000, @BikeDiscount = 1.0000, @SaleDiscount = 1.0000, @Color = 'Black', @ImageName = 'answer_stem_atac_pro.jpg', @MfrGrams = 200.00, @WSGrams = 0.00, @WSNotes = ''
select @P1
go
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[Stem] ([StemID], [ClampBolts], [Degree], [HandlebarClampSize], [IsFlipable], [IsShimable], [Length], [SteererTubeDiameter], [ThreadType])  VALUES (@StemID, @ClampBolts, @Degree, @HandlebarClampSize, @IsFlipable, @IsShimable, @Length, @SteererTubeDiameter, @ThreadType)', N'@StemID int,@ClampBolts tinyint,@Degree decimal(5,2),@HandlebarClampSize decimal(5,2),@IsFlipable bit,@IsShimable bit,@Length decimal(5,2),@SteererTubeDiameter decimal(5,2),@ThreadType char(2)', @StemID = NULL, @ClampBolts = 0, @Degree = 0.00, @HandlebarClampSize = 31.80, @IsFlipable = 1, @IsShimable = 0, @Length = 120.00, @SteererTubeDiameter = 38.10, @ThreadType = 'TL'
go
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION
go


daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 25-Sep-2007 08:45:15   

What are you doing at this.SetEntityDirty(...)? In general is better if you use yourEntity.SetNewFieldValue(fieldIndex, value); instead of **CurrentValue **property.

David Elizondo | LLBLGen Support Team
tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 25-Sep-2007 20:02:39   

daelmo wrote:

What are you doing at this.SetEntityDirty(...)? In general is better if you use yourEntity.SetNewFieldValue(fieldIndex, value); instead of **CurrentValue **property.

Here is the method SetEntityDirty which I got from another thread. I really don't understand why I would have to do this on each entity when the entity is new. I have tried with and without it and with it seems to work better as it causes more of the expected insert statements.


private void SetEntityDirty(IEntity2 entity)
{
    entity.IsNew = true;
    entity.IsDirty = true;

    for(int i=0; i < entity.Fields.Count; i++)
    {
        // don't mark the primary-keys and timestamps (DbType 19) as changed
        if ( !entity.Fields[i].IsPrimaryKey && entity.Fields[i].DataType != typeof(System.DateTime) )
        {
            entity.Fields[i].IsChanged = true;
        }
    }
}

I have also tried using SetNewFieldValue instead of Field.CurrentValue and I haven't seen any difference. Neither one causes the insert statements to get generated.

tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 25-Sep-2007 20:33:04   

I now have the following insert statement being generated which is closer to what I expect. The related part, in this case Stem, is still being left out for some reason. I guess the relation between the partInstance and the newProductVersion is not created. I just don't know why.


SET TRANSACTION ISOLATION LEVEL READ COMMITTED;BEGIN TRANSACTION [RecursiveSave]
go
declare @P1 int
set @P1=5955
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[Product] ([ActiveState], [ProductTypeID], [StyleCode], [ManufacturerID], [Model], [BaseModel], [ModelYear], [Warranty], [Material], [MaterialDescription], [WeightLimit], [Discount], [FreeShipping], [SortOrder], [CreateDate], [UpdateDate], [WSNotes], [ImageName], [Advertise], [AdvertisementImage], [ProductCatagoryID], [SizingImage], [BikeDiscount])  VALUES (@ActiveState, @ProductTypeID, @StyleCode, @ManufacturerID, @Model, @BaseModel, @ModelYear, @Warranty, @Material, @MaterialDescription, @WeightLimit, @Discount, @FreeShipping, @SortOrder, @CreateDate, @UpdateDate, @WSNotes, @ImageName, @Advertise, @AdvertisementImage, @ProductCatagoryID, @SizingImage, @BikeDiscount);SELECT @ProductID=SCOPE_IDENTITY()', N'@ProductID int output,@ActiveState char(3),@ProductTypeID int,@StyleCode char(2),@ManufacturerID int,@Model varchar(50),@BaseModel varchar(50),@ModelYear char(4),@Warranty char(4),@Material varchar(36),@MaterialDescription varchar(50),@WeightLimit decimal(5,2),@Discount decimal(5,4),@FreeShipping bit,@SortOrder smallint,@CreateDate datetime,@UpdateDate datetime,@WSNotes varchar(500),@ImageName varchar(50),@Advertise bit,@AdvertisementImage varchar(50),@ProductCatagoryID int,@SizingImage varchar(50),@BikeDiscount decimal(5,4)', @ProductID = @P1 output, @ActiveState = 'NEW', @ProductTypeID = 16, @StyleCode = 'M ', @ManufacturerID = 146, @Model = 'ATAC Pro', @BaseModel = '', @ModelYear = '2008', @Warranty = '   ', @Material = 'Aluminum', @MaterialDescription = '', @WeightLimit = 500.00, @Discount = 0.0000, @FreeShipping = 0, @SortOrder = 100, @CreateDate = 'May 30 2006  4:54:57:480PM', @UpdateDate = 'Sep 25 2007 11:21:59:537AM', @WSNotes = '', @ImageName = '', @Advertise = 0, @AdvertisementImage = '', @ProductCatagoryID = NULL, @SizingImage = '', @BikeDiscount = 1.0000
select @P1
go
declare @P1 int
set @P1=21189
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[ProductVersion] ([ProductID], [ActiveState], [Religion], [DistributorID], [DistributorNumber], [ManufacturerNumber], [IsPartSpecific], [OECostPrice], [OEPrice], [RPCostPrice], [RPPrice], [BikeDiscount], [SaleDiscount], [Color], [ImageName], [MfrGrams], [WSGrams], [WSNotes])  VALUES (@ProductID, @ActiveState, @Religion, @DistributorID, @DistributorNumber, @ManufacturerNumber, @IsPartSpecific, @OECostPrice, @OEPrice, @RPCostPrice, @RPPrice, @BikeDiscount, @SaleDiscount, @Color, @ImageName, @MfrGrams, @WSGrams, @WSNotes);SELECT @ProductVersionID=SCOPE_IDENTITY()', N'@ProductVersionID int output,@ProductID int,@ActiveState char(3),@Religion char(1),@DistributorID int,@DistributorNumber varchar(30),@ManufacturerNumber varchar(40),@IsPartSpecific bit,@OECostPrice smallmoney,@OEPrice smallmoney,@RPCostPrice smallmoney,@RPPrice smallmoney,@BikeDiscount decimal(5,4),@SaleDiscount decimal(5,4),@Color varchar(30),@ImageName varchar(50),@MfrGrams decimal(7,2),@WSGrams decimal(7,2),@WSNotes varchar(200)', @ProductVersionID = @P1 output, @ProductID = 5955, @ActiveState = 'NEW', @Religion = 'B', @DistributorID = 288, @DistributorNumber = '85-2139-new', @ManufacturerNumber = '', @IsPartSpecific = 0, @OECostPrice = $0.0000, @OEPrice = $0.0000, @RPCostPrice = $0.0000, @RPPrice = $0.0000, @BikeDiscount = 1.0000, @SaleDiscount = 1.0000, @Color = 'Black', @ImageName = 'answer_stem_atac_pro.jpg', @MfrGrams = 195.00, @WSGrams = 0.00, @WSNotes = ''
select @P1
go
declare @P1 int
set @P1=21190
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[ProductVersion] ([ProductID], [ActiveState], [Religion], [DistributorID], [DistributorNumber], [ManufacturerNumber], [IsPartSpecific], [OECostPrice], [OEPrice], [RPCostPrice], [RPPrice], [BikeDiscount], [SaleDiscount], [Color], [ImageName], [MfrGrams], [WSGrams], [WSNotes])  VALUES (@ProductID, @ActiveState, @Religion, @DistributorID, @DistributorNumber, @ManufacturerNumber, @IsPartSpecific, @OECostPrice, @OEPrice, @RPCostPrice, @RPPrice, @BikeDiscount, @SaleDiscount, @Color, @ImageName, @MfrGrams, @WSGrams, @WSNotes);SELECT @ProductVersionID=SCOPE_IDENTITY()', N'@ProductVersionID int output,@ProductID int,@ActiveState char(3),@Religion char(1),@DistributorID int,@DistributorNumber varchar(30),@ManufacturerNumber varchar(40),@IsPartSpecific bit,@OECostPrice smallmoney,@OEPrice smallmoney,@RPCostPrice smallmoney,@RPPrice smallmoney,@BikeDiscount decimal(5,4),@SaleDiscount decimal(5,4),@Color varchar(30),@ImageName varchar(50),@MfrGrams decimal(7,2),@WSGrams decimal(7,2),@WSNotes varchar(200)', @ProductVersionID = @P1 output, @ProductID = 5955, @ActiveState = 'NEW', @Religion = 'B', @DistributorID = 288, @DistributorNumber = '85-2143-new', @ManufacturerNumber = '', @IsPartSpecific = 0, @OECostPrice = $0.0000, @OEPrice = $0.0000, @RPCostPrice = $0.0000, @RPPrice = $0.0000, @BikeDiscount = 1.0000, @SaleDiscount = 1.0000, @Color = 'Black', @ImageName = 'answer_stem_atac_pro.jpg', @MfrGrams = 200.00, @WSGrams = 0.00, @WSNotes = ''
select @P1
go
declare @P1 int
set @P1=21191
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[ProductVersion] ([ProductID], [ActiveState], [Religion], [DistributorID], [DistributorNumber], [ManufacturerNumber], [IsPartSpecific], [OECostPrice], [OEPrice], [RPCostPrice], [RPPrice], [BikeDiscount], [SaleDiscount], [Color], [ImageName], [MfrGrams], [WSGrams], [WSNotes])  VALUES (@ProductID, @ActiveState, @Religion, @DistributorID, @DistributorNumber, @ManufacturerNumber, @IsPartSpecific, @OECostPrice, @OEPrice, @RPCostPrice, @RPPrice, @BikeDiscount, @SaleDiscount, @Color, @ImageName, @MfrGrams, @WSGrams, @WSNotes);SELECT @ProductVersionID=SCOPE_IDENTITY()', N'@ProductVersionID int output,@ProductID int,@ActiveState char(3),@Religion char(1),@DistributorID int,@DistributorNumber varchar(30),@ManufacturerNumber varchar(40),@IsPartSpecific bit,@OECostPrice smallmoney,@OEPrice smallmoney,@RPCostPrice smallmoney,@RPPrice smallmoney,@BikeDiscount decimal(5,4),@SaleDiscount decimal(5,4),@Color varchar(30),@ImageName varchar(50),@MfrGrams decimal(7,2),@WSGrams decimal(7,2),@WSNotes varchar(200)', @ProductVersionID = @P1 output, @ProductID = 5955, @ActiveState = 'NEW', @Religion = 'B', @DistributorID = 288, @DistributorNumber = '85-2137-new', @ManufacturerNumber = '', @IsPartSpecific = 0, @OECostPrice = $0.0000, @OEPrice = $0.0000, @RPCostPrice = $0.0000, @RPPrice = $0.0000, @BikeDiscount = 1.0000, @SaleDiscount = 1.0000, @Color = 'Black', @ImageName = 'answer_stem_atac_pro.jpg', @MfrGrams = 190.00, @WSGrams = 0.00, @WSNotes = ''
select @P1
go
declare @P1 int
set @P1=21192
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[ProductVersion] ([ProductID], [ActiveState], [Religion], [DistributorID], [DistributorNumber], [ManufacturerNumber], [IsPartSpecific], [OECostPrice], [OEPrice], [RPCostPrice], [RPPrice], [BikeDiscount], [SaleDiscount], [Color], [ImageName], [MfrGrams], [WSGrams], [WSNotes])  VALUES (@ProductID, @ActiveState, @Religion, @DistributorID, @DistributorNumber, @ManufacturerNumber, @IsPartSpecific, @OECostPrice, @OEPrice, @RPCostPrice, @RPPrice, @BikeDiscount, @SaleDiscount, @Color, @ImageName, @MfrGrams, @WSGrams, @WSNotes);SELECT @ProductVersionID=SCOPE_IDENTITY()', N'@ProductVersionID int output,@ProductID int,@ActiveState char(3),@Religion char(1),@DistributorID int,@DistributorNumber varchar(30),@ManufacturerNumber varchar(40),@IsPartSpecific bit,@OECostPrice smallmoney,@OEPrice smallmoney,@RPCostPrice smallmoney,@RPPrice smallmoney,@BikeDiscount decimal(5,4),@SaleDiscount decimal(5,4),@Color varchar(30),@ImageName varchar(50),@MfrGrams decimal(7,2),@WSGrams decimal(7,2),@WSNotes varchar(200)', @ProductVersionID = @P1 output, @ProductID = 5955, @ActiveState = 'NEW', @Religion = 'B', @DistributorID = 288, @DistributorNumber = '85-2131-new', @ManufacturerNumber = '', @IsPartSpecific = 0, @OECostPrice = $0.0000, @OEPrice = $0.0000, @RPCostPrice = $0.0000, @RPPrice = $0.0000, @BikeDiscount = 1.0000, @SaleDiscount = 1.0000, @Color = 'Black', @ImageName = 'answer_stem_atac_pro.jpg', @MfrGrams = 185.00, @WSGrams = 0.00, @WSNotes = ''
select @P1
go
declare @P1 int
set @P1=21193
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[ProductVersion] ([ProductID], [ActiveState], [Religion], [DistributorID], [DistributorNumber], [ManufacturerNumber], [IsPartSpecific], [OECostPrice], [OEPrice], [RPCostPrice], [RPPrice], [BikeDiscount], [SaleDiscount], [Color], [ImageName], [MfrGrams], [WSGrams], [WSNotes])  VALUES (@ProductID, @ActiveState, @Religion, @DistributorID, @DistributorNumber, @ManufacturerNumber, @IsPartSpecific, @OECostPrice, @OEPrice, @RPCostPrice, @RPPrice, @BikeDiscount, @SaleDiscount, @Color, @ImageName, @MfrGrams, @WSGrams, @WSNotes);SELECT @ProductVersionID=SCOPE_IDENTITY()', N'@ProductVersionID int output,@ProductID int,@ActiveState char(3),@Religion char(1),@DistributorID int,@DistributorNumber varchar(30),@ManufacturerNumber varchar(40),@IsPartSpecific bit,@OECostPrice smallmoney,@OEPrice smallmoney,@RPCostPrice smallmoney,@RPPrice smallmoney,@BikeDiscount decimal(5,4),@SaleDiscount decimal(5,4),@Color varchar(30),@ImageName varchar(50),@MfrGrams decimal(7,2),@WSGrams decimal(7,2),@WSNotes varchar(200)', @ProductVersionID = @P1 output, @ProductID = 5955, @ActiveState = 'NEW', @Religion = 'B', @DistributorID = 288, @DistributorNumber = '85-2127-new', @ManufacturerNumber = '', @IsPartSpecific = 0, @OECostPrice = $0.0000, @OEPrice = $0.0000, @RPCostPrice = $0.0000, @RPPrice = $0.0000, @BikeDiscount = 1.0000, @SaleDiscount = 1.0000, @Color = 'Black', @ImageName = 'answer_stem_atac_pro.jpg', @MfrGrams = 180.00, @WSGrams = 0.00, @WSNotes = ''
select @P1
go
declare @P1 int
set @P1=21194
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[ProductVersion] ([ProductID], [ActiveState], [Religion], [DistributorID], [DistributorNumber], [ManufacturerNumber], [IsPartSpecific], [OECostPrice], [OEPrice], [RPCostPrice], [RPPrice], [BikeDiscount], [SaleDiscount], [Color], [ImageName], [MfrGrams], [WSGrams], [WSNotes])  VALUES (@ProductID, @ActiveState, @Religion, @DistributorID, @DistributorNumber, @ManufacturerNumber, @IsPartSpecific, @OECostPrice, @OEPrice, @RPCostPrice, @RPPrice, @BikeDiscount, @SaleDiscount, @Color, @ImageName, @MfrGrams, @WSGrams, @WSNotes);SELECT @ProductVersionID=SCOPE_IDENTITY()', N'@ProductVersionID int output,@ProductID int,@ActiveState char(3),@Religion char(1),@DistributorID int,@DistributorNumber varchar(30),@ManufacturerNumber varchar(40),@IsPartSpecific bit,@OECostPrice smallmoney,@OEPrice smallmoney,@RPCostPrice smallmoney,@RPPrice smallmoney,@BikeDiscount decimal(5,4),@SaleDiscount decimal(5,4),@Color varchar(30),@ImageName varchar(50),@MfrGrams decimal(7,2),@WSGrams decimal(7,2),@WSNotes varchar(200)', @ProductVersionID = @P1 output, @ProductID = 5955, @ActiveState = 'NEW', @Religion = 'B', @DistributorID = 288, @DistributorNumber = '85-2135-new', @ManufacturerNumber = '', @IsPartSpecific = 0, @OECostPrice = $0.0000, @OEPrice = $0.0000, @RPCostPrice = $0.0000, @RPPrice = $0.0000, @BikeDiscount = 1.0000, @SaleDiscount = 1.0000, @Color = 'Black', @ImageName = 'answer_stem_atac_pro.jpg', @MfrGrams = 190.00, @WSGrams = 0.00, @WSNotes = ''
select @P1
go
declare @P1 int
set @P1=21195
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[ProductVersion] ([ProductID], [ActiveState], [Religion], [DistributorID], [DistributorNumber], [ManufacturerNumber], [IsPartSpecific], [OECostPrice], [OEPrice], [RPCostPrice], [RPPrice], [BikeDiscount], [SaleDiscount], [Color], [ImageName], [MfrGrams], [WSGrams], [WSNotes])  VALUES (@ProductID, @ActiveState, @Religion, @DistributorID, @DistributorNumber, @ManufacturerNumber, @IsPartSpecific, @OECostPrice, @OEPrice, @RPCostPrice, @RPPrice, @BikeDiscount, @SaleDiscount, @Color, @ImageName, @MfrGrams, @WSGrams, @WSNotes);SELECT @ProductVersionID=SCOPE_IDENTITY()', N'@ProductVersionID int output,@ProductID int,@ActiveState char(3),@Religion char(1),@DistributorID int,@DistributorNumber varchar(30),@ManufacturerNumber varchar(40),@IsPartSpecific bit,@OECostPrice smallmoney,@OEPrice smallmoney,@RPCostPrice smallmoney,@RPPrice smallmoney,@BikeDiscount decimal(5,4),@SaleDiscount decimal(5,4),@Color varchar(30),@ImageName varchar(50),@MfrGrams decimal(7,2),@WSGrams decimal(7,2),@WSNotes varchar(200)', @ProductVersionID = @P1 output, @ProductID = 5955, @ActiveState = 'NEW', @Religion = 'B', @DistributorID = 288, @DistributorNumber = '85-2133-new', @ManufacturerNumber = '', @IsPartSpecific = 0, @OECostPrice = $0.0000, @OEPrice = $0.0000, @RPCostPrice = $0.0000, @RPPrice = $0.0000, @BikeDiscount = 1.0000, @SaleDiscount = 1.0000, @Color = 'Black', @ImageName = 'answer_stem_atac_pro.jpg', @MfrGrams = 185.00, @WSGrams = 0.00, @WSNotes = ''
select @P1
go
declare @P1 int
set @P1=21196
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[ProductVersion] ([ProductID], [ActiveState], [Religion], [DistributorID], [DistributorNumber], [ManufacturerNumber], [IsPartSpecific], [OECostPrice], [OEPrice], [RPCostPrice], [RPPrice], [BikeDiscount], [SaleDiscount], [Color], [ImageName], [MfrGrams], [WSGrams], [WSNotes])  VALUES (@ProductID, @ActiveState, @Religion, @DistributorID, @DistributorNumber, @ManufacturerNumber, @IsPartSpecific, @OECostPrice, @OEPrice, @RPCostPrice, @RPPrice, @BikeDiscount, @SaleDiscount, @Color, @ImageName, @MfrGrams, @WSGrams, @WSNotes);SELECT @ProductVersionID=SCOPE_IDENTITY()', N'@ProductVersionID int output,@ProductID int,@ActiveState char(3),@Religion char(1),@DistributorID int,@DistributorNumber varchar(30),@ManufacturerNumber varchar(40),@IsPartSpecific bit,@OECostPrice smallmoney,@OEPrice smallmoney,@RPCostPrice smallmoney,@RPPrice smallmoney,@BikeDiscount decimal(5,4),@SaleDiscount decimal(5,4),@Color varchar(30),@ImageName varchar(50),@MfrGrams decimal(7,2),@WSGrams decimal(7,2),@WSNotes varchar(200)', @ProductVersionID = @P1 output, @ProductID = 5955, @ActiveState = 'NEW', @Religion = 'B', @DistributorID = 288, @DistributorNumber = '85-2129-new', @ManufacturerNumber = '', @IsPartSpecific = 0, @OECostPrice = $0.0000, @OEPrice = $0.0000, @RPCostPrice = $0.0000, @RPPrice = $0.0000, @BikeDiscount = 1.0000, @SaleDiscount = 1.0000, @Color = 'Black', @ImageName = 'answer_stem_atac_pro.jpg', @MfrGrams = 180.00, @WSGrams = 0.00, @WSNotes = ''
select @P1
go
declare @P1 int
set @P1=21197
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[ProductVersion] ([ProductID], [ActiveState], [Religion], [DistributorID], [DistributorNumber], [ManufacturerNumber], [IsPartSpecific], [OECostPrice], [OEPrice], [RPCostPrice], [RPPrice], [BikeDiscount], [SaleDiscount], [Color], [ImageName], [MfrGrams], [WSGrams], [WSNotes])  VALUES (@ProductID, @ActiveState, @Religion, @DistributorID, @DistributorNumber, @ManufacturerNumber, @IsPartSpecific, @OECostPrice, @OEPrice, @RPCostPrice, @RPPrice, @BikeDiscount, @SaleDiscount, @Color, @ImageName, @MfrGrams, @WSGrams, @WSNotes);SELECT @ProductVersionID=SCOPE_IDENTITY()', N'@ProductVersionID int output,@ProductID int,@ActiveState char(3),@Religion char(1),@DistributorID int,@DistributorNumber varchar(30),@ManufacturerNumber varchar(40),@IsPartSpecific bit,@OECostPrice smallmoney,@OEPrice smallmoney,@RPCostPrice smallmoney,@RPPrice smallmoney,@BikeDiscount decimal(5,4),@SaleDiscount decimal(5,4),@Color varchar(30),@ImageName varchar(50),@MfrGrams decimal(7,2),@WSGrams decimal(7,2),@WSNotes varchar(200)', @ProductVersionID = @P1 output, @ProductID = 5955, @ActiveState = 'NEW', @Religion = 'B', @DistributorID = 288, @DistributorNumber = '85-2125-new', @ManufacturerNumber = '', @IsPartSpecific = 0, @OECostPrice = $0.0000, @OEPrice = $0.0000, @RPCostPrice = $0.0000, @RPPrice = $0.0000, @BikeDiscount = 1.0000, @SaleDiscount = 1.0000, @Color = 'Black', @ImageName = 'answer_stem_atac_pro.jpg', @MfrGrams = 180.00, @WSGrams = 0.00, @WSNotes = ''
select @P1
go
declare @P1 int
set @P1=21198
exec sp_executesql N'INSERT INTO [WS2_Copy].[dbo].[ProductVersion] ([ProductID], [ActiveState], [Religion], [DistributorID], [DistributorNumber], [ManufacturerNumber], [IsPartSpecific], [OECostPrice], [OEPrice], [RPCostPrice], [RPPrice], [BikeDiscount], [SaleDiscount], [Color], [ImageName], [MfrGrams], [WSGrams], [WSNotes])  VALUES (@ProductID, @ActiveState, @Religion, @DistributorID, @DistributorNumber, @ManufacturerNumber, @IsPartSpecific, @OECostPrice, @OEPrice, @RPCostPrice, @RPPrice, @BikeDiscount, @SaleDiscount, @Color, @ImageName, @MfrGrams, @WSGrams, @WSNotes);SELECT @ProductVersionID=SCOPE_IDENTITY()', N'@ProductVersionID int output,@ProductID int,@ActiveState char(3),@Religion char(1),@DistributorID int,@DistributorNumber varchar(30),@ManufacturerNumber varchar(40),@IsPartSpecific bit,@OECostPrice smallmoney,@OEPrice smallmoney,@RPCostPrice smallmoney,@RPPrice smallmoney,@BikeDiscount decimal(5,4),@SaleDiscount decimal(5,4),@Color varchar(30),@ImageName varchar(50),@MfrGrams decimal(7,2),@WSGrams decimal(7,2),@WSNotes varchar(200)', @ProductVersionID = @P1 output, @ProductID = 5955, @ActiveState = 'NEW', @Religion = 'B', @DistributorID = 288, @DistributorNumber = '85-2145-new', @ManufacturerNumber = '', @IsPartSpecific = 0, @OECostPrice = $0.0000, @OEPrice = $0.0000, @RPCostPrice = $0.0000, @RPPrice = $0.0000, @BikeDiscount = 1.0000, @SaleDiscount = 1.0000, @Color = 'Black', @ImageName = 'answer_stem_atac_pro.jpg', @MfrGrams = 200.00, @WSGrams = 0.00, @WSNotes = ''
select @P1
go

Here is the code that goes along with the insert statement.


public ProductEntity DuplicateProduct(ProductEntity product)
{
    ProductEntity newProduct = new ProductEntity();
    string productTypeName = product.ProductType.TypeName;

    // Iterate over the fields to copy.
    foreach(EntityField2 field in product.Fields)
    {
        string fieldName = field.Name;

        // Skip the ID fields so that LLBLGen runtime re-creates the ID's.
        if ( field.IsPrimaryKey )
            continue;

        object currentFieldValue = product.Fields[fieldName].CurrentValue;

        // Fields in unique constraints must have their values customized or the entity won't save.
        switch(fieldName)
        {
            case "ActiveState":
                currentFieldValue = "NEW";
                break;
            case "ModelYear":
                currentFieldValue = Convert.ToString(DateTime.Now.Year + 1);
                break;
        }

        // Copy the field values.
        newProduct.SetNewFieldValue(fieldName, currentFieldValue);
    }

    foreach(ProductVersionEntity productVersion in product.ProductVersion)
    {
        ProductVersionEntity newProductVersion = new ProductVersionEntity();

        // Iterate over the fields to copy.
        foreach(EntityField2 field in productVersion.Fields)
        {
            string fieldName = field.Name;

            // Skip the ID fields so that LLBLGen runtime re-creates the ID's.
            if ( fieldName == "ProductVersionID" || fieldName == "ProductID" )
                continue;

            object currentFieldValue = productVersion.Fields[fieldName].CurrentValue;
            
            // Fields in unique constraints must have their values customized or the entity won't save.
            switch(fieldName)
            {
                case "ActiveState":
                    currentFieldValue = "NEW";
                    break;
                case "DistributorNumber":
                    currentFieldValue += "-new";
                    break;
                case "OECostPrice":
                    currentFieldValue = 0.00M;
                    break;
                case "OEPrice":
                    currentFieldValue = 0.00M;
                    break;
                case "RPCostPrice":
                    currentFieldValue = 0.00M;
                    break;
                case "RPPrice":
                    currentFieldValue = 0.00M;
                    break;
            }

            // Copy the field values.
            newProductVersion.SetNewFieldValue(fieldName, currentFieldValue);
        }

        // Get an instance of the part entity to copy.
        // This would be someting like ProductVersion.Stem.
        EntityBase2 currentPart = (EntityBase2)productVersion.GetType().GetProperty(productTypeName).GetValue(productVersion, new object[0]);
        if ( currentPart != null )
        {                   
            // Create new instance of part being copied.
            Assembly assembly = Assembly.GetAssembly(typeof(ProductEntity));
            Type partType = assembly.GetType("WrenchScience.LLBLGen.EntityClasses." + productTypeName + "Entity");
            EntityBase2 partInstance = (EntityBase2)partType.GetConstructor(new Type[0]).Invoke(new object[0]);

            // Add related part to ProductVersion.
            partInstance.SetRelatedEntity(newProductVersion, "ProductVersion");

            // Iterate over the fields to copy.
            foreach(EntityField2 field in currentPart.Fields)
            {
                string fieldName = field.Name;
                
                // Skip the ID fields so that LLBLGen runtime re-creates the ID's.
                if ( fieldName == "ProductVersionID" || fieldName == productTypeName + "ID" )
                    continue;

                // Copy the field values.
                partInstance.SetNewFieldValue(fieldName, field.CurrentValue);
            }
        }

        // Add ProductVersion to Product.ProductVersion collection.
        newProduct.ProductVersion.Add(newProductVersion);
    }

tprohas
User
Posts: 257
Joined: 23-Mar-2004
# Posted on: 25-Sep-2007 21:07:59   

OK, I've got it!

Finally it's all working. Below is the method that works for anyone else who might want to do the same thing.

I do have a question though. Why does the following two lines differ in the way they work. The first line does not work and the second does work.

Does not work:

partInstance.SetRelatedEntity(newProductVersion, "ProductVersion");

Does work:

partInstance.GetType().GetProperty("ProductVersion", typeof(ProductVersionEntity)).SetValue(partInstance, newProductVersion, new object[0]);

Here is the working version of the method:


/// <summary>
/// Duplicates an entity in the database. Primarily used for creating a new model product from a previous years product.
/// </summary>
/// <param name="product"></param>
public ProductEntity DuplicateProduct(ProductEntity product)
{
    ProductEntity newProduct = new ProductEntity();
    string productTypeName = product.ProductType.TypeName;

    // Iterate over the fields to copy.
    foreach(EntityField2 field in product.Fields)
    {
        string fieldName = field.Name;

        // Skip the ID fields so that LLBLGen runtime re-creates the ID's.
        if ( field.IsPrimaryKey )
            continue;

        object currentFieldValue = product.Fields[fieldName].CurrentValue;

        // Fields in unique constraints must have their values customized or the entity won't save.
        switch(fieldName)
        {
            case "ActiveState":
                currentFieldValue = "NEW";
                break;
            case "ModelYear":
                currentFieldValue = Convert.ToString(DateTime.Now.Year + 1);
                break;
        }

        // Copy the field values.
        newProduct.SetNewFieldValue(fieldName, currentFieldValue);
    }

    foreach(ProductVersionEntity productVersion in product.ProductVersion)
    {
        ProductVersionEntity newProductVersion = new ProductVersionEntity();

        // Get an instance of the part entity to copy.
        // This would be someting like ProductVersion.Stem.
        EntityBase2 currentPart = (EntityBase2)productVersion.GetType().GetProperty(productTypeName).GetValue(productVersion, new object[0]);
        if ( currentPart != null )
        {                   
            // Create new instance of part being copied.
            Assembly assembly = Assembly.GetAssembly(typeof(ProductEntity));
            Type partType = assembly.GetType("WrenchScience.LLBLGen.EntityClasses." + productTypeName + "Entity");
            EntityBase2 partInstance = (EntityBase2)partType.GetConstructor(new Type[0]).Invoke(new object[0]);

            // Add related part to ProductVersion.
            partInstance.SetRelatedEntity(newProduct, "Product");
            //partInstance.SetRelatedEntity(newProductVersion, "ProductVersion");
            partInstance.GetType().GetProperty("ProductVersion", typeof(ProductVersionEntity)).SetValue(partInstance, newProductVersion, new object[0]);

            // Iterate over the fields to copy.
            foreach(EntityField2 field in currentPart.Fields)
            {
                string fieldName = field.Name;
                
                // Skip the ID fields so that LLBLGen runtime re-creates the ID's.
                if ( fieldName == "ProductVersionID" || fieldName == productTypeName + "ID" )
                    continue;

                // Copy the field values.
                partInstance.SetNewFieldValue(fieldName, field.CurrentValue);
            }
        }

        // Iterate over the fields to copy.
        foreach(EntityField2 field in productVersion.Fields)
        {
            string fieldName = field.Name;

            // Skip the ID fields so that LLBLGen runtime re-creates the ID's.
            if ( fieldName == "ProductVersionID" || fieldName == "ProductID" )
                continue;

            object currentFieldValue = productVersion.Fields[fieldName].CurrentValue;
            
            // Fields in unique constraints must have their values customized or the entity won't save.
            switch(fieldName)
            {
                case "ActiveState":
                    currentFieldValue = "NEW";
                    break;
                case "DistributorNumber":
                    currentFieldValue += "-new";
                    break;
                case "OECostPrice":
                    currentFieldValue = 0.00M;
                    break;
                case "OEPrice":
                    currentFieldValue = 0.00M;
                    break;
                case "RPCostPrice":
                    currentFieldValue = 0.00M;
                    break;
                case "RPPrice":
                    currentFieldValue = 0.00M;
                    break;
            }

            // Copy the field values.
            newProductVersion.SetNewFieldValue(fieldName, currentFieldValue);
        }

        // Add ProductVersion to Product.ProductVersion collection.
        newProduct.ProductVersion.Add(newProductVersion);
    }

    return newProduct;
}