Multiple Wishlist bug
Posted: Mon Aug 18, 2014 8:46 am
We had some errors show up related to Wishlists not being 1:1 with Users. Here is the error log detail:
An error has occured at https://www.onlinescuba.com/Login.aspx
Exception: Exception of type 'System.Web.HttpUnhandledException' was thrown. Stack Trace: at System.Web.UI.Page.HandleError(Exception e) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest() at System.Web.UI.Page.ProcessRequest(HttpContext context) at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) Inner Exception: query did not return a unique result: 2 Inner Exception Stack Trace: at NHibernate.Impl.AbstractQueryImpl.UniqueElement(IList list) at NHibernate.Impl.CriteriaImpl.UniqueResult[T]() at CommerceBuilder.Users.Wishlist.Transfer(Int32 sourceId, Int32 targetId, Boolean transferEmptyWishlist) at CommerceBuilder.Users.User.Migrate(User oldUser, User newUser, Boolean includeOrderData, Boolean isNewUserAccount, Boolean migrateBasketShipments) at CommerceBuilder.Users.User.Migrate(User oldUser, User newUser) at AbleCommerce.ConLib.LoginDialog.LoginButton_Click(Object sender, EventArgs e) at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
I looked into it and it appears that there is nothing stopping the Wishlists table from creating multiple records for a given user, however the Wishlist.Transfer method runs a query that requires a UniqueResult<Wishlist>();
The user's wishlists are actually queried more than once - the first time it queries correctly, returning a list of wishlists for the user. The second time it imposes the UniqueResult contraint, which is causing an error. This is in CommerceBuilder > Users > Wishlist.cs, lines 61-97 of the latest build (R8b7345)
I haven't looked deep enough into the code to determine if the intention is for users to be able to have multiple wishlists or if they were supposed to be unique, but whichever it is the code needs to be consistent when loading them, and if they are supposed to be unique then there needs to be mechanisms in place to prevent multiple wishlists from being created.
An error has occured at https://www.onlinescuba.com/Login.aspx
Exception: Exception of type 'System.Web.HttpUnhandledException' was thrown. Stack Trace: at System.Web.UI.Page.HandleError(Exception e) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest() at System.Web.UI.Page.ProcessRequest(HttpContext context) at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) Inner Exception: query did not return a unique result: 2 Inner Exception Stack Trace: at NHibernate.Impl.AbstractQueryImpl.UniqueElement(IList list) at NHibernate.Impl.CriteriaImpl.UniqueResult[T]() at CommerceBuilder.Users.Wishlist.Transfer(Int32 sourceId, Int32 targetId, Boolean transferEmptyWishlist) at CommerceBuilder.Users.User.Migrate(User oldUser, User newUser, Boolean includeOrderData, Boolean isNewUserAccount, Boolean migrateBasketShipments) at CommerceBuilder.Users.User.Migrate(User oldUser, User newUser) at AbleCommerce.ConLib.LoginDialog.LoginButton_Click(Object sender, EventArgs e) at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
I looked into it and it appears that there is nothing stopping the Wishlists table from creating multiple records for a given user, however the Wishlist.Transfer method runs a query that requires a UniqueResult<Wishlist>();
The user's wishlists are actually queried more than once - the first time it queries correctly, returning a list of wishlists for the user. The second time it imposes the UniqueResult contraint, which is causing an error. This is in CommerceBuilder > Users > Wishlist.cs, lines 61-97 of the latest build (R8b7345)
Code: Select all
public static void Transfer(int sourceId, int targetId, bool transferEmptyWishlist)
{
if (sourceId != targetId)
{
// GET THE DEFAULT BASKET FOR THE SOURCE USER
IList<Wishlist> sourceWishlists = AbleContext.Resolve<IWishlistRepository>().LoadForUser(sourceId); /**** THIS IS CORRECT ****/
if (sourceWishlists.Count == 0) return;
Wishlist sourceWishlist = sourceWishlists[0];
if (!transferEmptyWishlist)
{
// WE SHOULD NOT TRANSFER EMPTY BASKETS, COUNT THE SOURCE ITEMS
int sourceCount = AbleContext.Resolve<IWishlistItemRepository>().CountForWishlist(sourceWishlist.Id);
if (sourceCount == 0) return;
}
// DETERMINE WHETHER USER HAS A WISHLIST ALREADY
Wishlist wishlist = NHibernateHelper.CreateCriteria<Wishlist>()
.Add(Restrictions.Eq("User.Id", targetId))
.UniqueResult<Wishlist>(); /**** THIS IS THE SOURCE OF THE ERROR ****/
int targetWishlistId = wishlist != null ? wishlist.Id : 0;
if (targetWishlistId == 0)
{
// USER HAS NO WISHLIST, SO MOVE THE SOURCE WISHLIST TO NEW USER
sourceWishlist.User = AbleContext.Resolve<IUserRepository>().Load(targetId);
sourceWishlist.Save();
}
else
{
// USER HAS A WISHLIST, JUST MOVE ITEMS FROM SOURCE TO TARGET
NHibernateHelper.CreateSQLQuery("update ac_WishlistItems set WishlistId = :targetWishlistId where WishlistId = :sourceWishlistId")
.SetInt32("targetWishlistId", targetWishlistId)
.SetInt32("sourceWishlistId", sourceWishlist.Id)
.ExecuteUpdate();
}
}
}