var product = new Product
{
Sku = "SKU-123456",
Name = "My Product",
AllowOrdering = true,
DisplayOnSite = true,
ProductDefinitionId = 1, // Set to an existing defintion
ThumbnailImageMediaId = 1 // ID from Umbraco (nullable int)
};
product.Save();
Which I think is incorrect because ProductDefinitionId is no longer a member of product - it is now ProductDefinition which is in line with the Hibernate approach to defining join links.
Do you agree ?
Anyway here is the code I wrote which works OK and can be used as similar sample for the current version:
First you need to define the following reference:
UCommerce = \bin\UCommerce.dll
Add and the following Using directives:
using UCommerce;
using UCommerce.EntitiesV2;
and here is the code I added:
var productDefinition = ProductDefinition.FirstOrDefault(x => x.Name == "Special Clancy Product 2");
if (productDefinition == null)
{
// If productDefinition does not exist then create it
productDefinition = new ProductDefinition
{
Description = "Special Clancy Description 2",
Name = "Special Clancy Product 2",
};
productDefinition.Save();
}
else
{
}
DateTime now = DateTime.Now;
TextBoxSKU.Text = "TCSKU_" + now.ToString(); // Add time string to ensure SKU uniqueness
TextBoxName.Text = "TCDesc";
var product = new Product
{
Sku = TextBoxSKU.Text,
Name = TextBoxName.Text.ToString(),
AllowOrdering = true,
DisplayOnSite = true,
ProductDefinition = productDefinition, // Set to an existing defintion
ThumbnailImageMediaId = null // ID from Umbraco (nullable int)
};
product.Save();
var productDescription = new ProductDescription
{
CultureCode = "en-US", // or en-GB, da-DK etc.
DisplayName = "TC display name",
ShortDescription = "TC short description",
LongDescription = "TC long description",
Product = product
};
productDescription.Save();
product.AddProductDescription(productDescription);
//Currency xxcurrency = (Currency) session. Find("select CurrencyId where ")
var currency = Currency.SingleOrDefault(x => x.ISOCode == "USD");
var priceGroup = PriceGroup.FirstOrDefault(x => x.Name == "USD_ZDZT");
if (priceGroup == null)
{
// If price group does not exist then create it
priceGroup = new PriceGroup()
{
Currency = currency,
Description = "USD Zero Discount Zero Tax",
Name = "USD_ZDZT",
VATRate = 0
};
priceGroup.Save();
}
else
{
}
var priceGroupPrice = new PriceGroupPrice
{
Product = product,
PriceGroup = priceGroup,
Price = 499.95m
};
priceGroupPrice.Save();
product.AddPriceGroupPrice(priceGroupPrice);
Have my H5YR. thanks for being so awsome and not only pointing this out, but also suggesting a fix for it. I will make sure to update the docs for the proper version ASAP.
So my code works but I am new to nHibernate and there is one thing I do not understand ...
Looking at the following code:
var product = new Product
{
Sku = TextBoxSKU.Text,
Name = TextBoxName.Text.ToString(),
AllowOrdering = true,
DisplayOnSite = true,
ProductDefinition = productDefinition, // Set to an existing defintion
ThumbnailImageMediaId = null // ID from Umbraco (nullable int)
};
product.Save();
var productDescription = new ProductDescription
{
CultureCode = "en-US", // or en-GB, da-DK etc.
DisplayName = "TC display name",
ShortDescription = "TC short description",
LongDescription = "TC long description",
Product = product // <<<< This line seems to link/join Product and ProudctDescription
};
productDescription.Save();
product.AddProductDescription(productDescription); // <<<< This line ALSO seems to link/join Product and ProudctDescription ???
This line
Product = product // <<<< This line seems to link/join Product and ProudctDescription
Seems to link/join Product and ProudctDescription but then the following line seems to do the same:
product.AddProductDescription(productDescription); // <<<< This line ALSO seems to link/join Product and ProudctDescription ???
Can you help me understand the exact purpose and difference between these two line ? Are they both required, are they redundant ?
In the relational world, the link between the product and the product description is represented using only one piece of data: The id of the Product in the row representing the ProductDescription in the database table uCommerce_ProductDescription.
In the object world however, the link is represented both as a reference from the ProductDescription instance to the Product instance, but also as a reference to the ProductDescription instance in a collection of ProductDescription references on the Product instance.
Both representations needs to be set up, in order for the object graph to be consistant.
I will elaborate a little bit, hopefully without adding to much confusion! :-)
The same piece of information is represented twice, and nhibernate does not enforce consistancy when a relation is modified. The last bit is important! If you take a ProductDescription object, and sets the product to reference a different product, nhibernate will not remove the reference to the collection of descriptions on the "old" product. Nor will it insert a new reference in the description collection on the "new" product. You have to maintain both ends of the relation your self, when modifying a relation. It is very easy to get an inconsistant object graph. :-S
When you set up the nhibernate map, you specify which end is responsible for maintaining the relation. Ie. which end of the link is the "master".
In this particular instance, the relationship is maintained by the ProducDescription reference to the Product.
So if you were to create a new ProductDescription instance and simply adding it directly to the collection of the Product, the link would not be persisted. If you on the other hand were to create a new ProductDescription and assign its Product property, then the relation would be persisted, even if you did not add the relation to the collection on product. And in this case, the object graph would be inconsistant, until it is re-read. At which point nhibernate would populate both ends of the relation.
And finally, the answer to your question: :-D
In this particular instance, you only need the last line. This is because the custom code inside the AddProductDescription() method also sets the Product reference on the ProductDescription instance.
ORM modelling is quite complex. I advise you to read more descriptions of it, in order to become more familiar with it. This very simplistic description I have given is definitely not "the whole thruth". :-)
And when you add caching of objects and collections on top of it, it becomes even more complex.
Incorrect Sample Code on uCommerce Documentation on How to Create a product using the API
Sample Code in uCommerce Documentation on How to Create a product using the API at http://docs.ucommerce.net/ucommerce/v6/how-to/Create-a-product-using-the-api.html seems incorrect - perhaps it is out of date and based on a version of uCommerce before the use of nHibernate ?
For example it includes the following code:
Which I think is incorrect because ProductDefinitionId is no longer a member of product - it is now ProductDefinition which is in line with the Hibernate approach to defining join links.
Do you agree ?
Anyway here is the code I wrote which works OK and can be used as similar sample for the current version:
First you need to define the following reference:
UCommerce = \bin\UCommerce.dll
Add and the following Using directives:
using UCommerce; using UCommerce.EntitiesV2;
and here is the code I added:
I hope this helps someone and feel free to use this to replace the old code at http://docs.ucommerce.net/ucommerce/v6/how-to/Create-a-product-using-the-api.html if appropriate.
Terry Clancy ClanceZ
Do you agree ?
I Totally agree :)
And hi Terry,
Have my H5YR. thanks for being so awsome and not only pointing this out, but also suggesting a fix for it. I will make sure to update the docs for the proper version ASAP.
Thanks very much Moren.
So my code works but I am new to nHibernate and there is one thing I do not understand ...
Looking at the following code:
This line
Seems to link/join Product and ProudctDescription but then the following line seems to do the same:
Can you help me understand the exact purpose and difference between these two line ? Are they both required, are they redundant ?
Thanks
Terry
Hello Terry,
In the relational world, the link between the product and the product description is represented using only one piece of data: The id of the Product in the row representing the ProductDescription in the database table uCommerce_ProductDescription.
In the object world however, the link is represented both as a reference from the ProductDescription instance to the Product instance, but also as a reference to the ProductDescription instance in a collection of ProductDescription references on the Product instance.
Both representations needs to be set up, in order for the object graph to be consistant.
I will elaborate a little bit, hopefully without adding to much confusion! :-)
The same piece of information is represented twice, and nhibernate does not enforce consistancy when a relation is modified. The last bit is important! If you take a ProductDescription object, and sets the product to reference a different product, nhibernate will not remove the reference to the collection of descriptions on the "old" product. Nor will it insert a new reference in the description collection on the "new" product. You have to maintain both ends of the relation your self, when modifying a relation. It is very easy to get an inconsistant object graph. :-S
When you set up the nhibernate map, you specify which end is responsible for maintaining the relation. Ie. which end of the link is the "master".
In this particular instance, the relationship is maintained by the ProducDescription reference to the Product.
So if you were to create a new ProductDescription instance and simply adding it directly to the collection of the Product, the link would not be persisted.
If you on the other hand were to create a new ProductDescription and assign its Product property, then the relation would be persisted, even if you did not add the relation to the collection on product. And in this case, the object graph would be inconsistant, until it is re-read. At which point nhibernate would populate both ends of the relation.
And finally, the answer to your question: :-D
In this particular instance, you only need the last line. This is because the custom code inside the AddProductDescription() method also sets the Product reference on the ProductDescription instance.
ORM modelling is quite complex. I advise you to read more descriptions of it, in order to become more familiar with it. This very simplistic description I have given is definitely not "the whole thruth". :-)
And when you add caching of objects and collections on top of it, it becomes even more complex.
Kind regards,
Jesper
is working on a reply...