Я столкнулся со странной проблемой, когда при многократном вызове SaveChanges()
с использованием вложенных экземпляров контекста (т. Е. С помощью использования для создания экземпляра контекста) он вставляет дублирующее содержимое вместо его обновления.
По сути, я вложил два контекста, вставил две строки в две разные таблицы (используя два разных контекста) и затем обновил одну из этих строк.
т.е.
Вставить в таблицу А
Вставить в таблицу B
Обновить таблицу A значением из таблицы B
В тот момент, когда я иду к обновлению таблицы A, она успешно обновляет строку по мере необходимости, но также вставляет дублирующую строку (без обновленных значений).
Может ли кто-нибудь пролить свет на то, почему это может произойти?
Приветствия
Gavin
Редактировать: Извините, я знал, что должен был опубликовать некоторый код, чтобы помочь, но я думал, что это может смутить людей.
public ActionResult Payment(int packageID, string action)
{
int c = 0;
using (PackageContext pc = new PackageContext())
{
Package selectedPackage = pc.Packages.Find(packageID);
// store the user's package
UserSubscriptionHistory sub;
using (UserSubscriptionHistoryContext ushc = new UserSubscriptionHistoryContext())
{
sub = new UserSubscriptionHistory();
sub.UserID = Core.CurrentUserID;
sub.PackageID = packageID;
sub.Duration = selectedPackage.Duration;
sub.Cost = selectedPackage.Cost;
ushc.History.Add(sub);
c = ushc.SaveChanges(); // c returns 1 row changed, as one row is inserted
if (c == 0)
{
throw new Exception("An unknown error occured");
}
// has the user selected a trial package?
if (!selectedPackage.IsTrial.HasValue || !selectedPackage.IsTrial.Value)
{
// get me some money ;)
Paypal pp = new Paypal();
PaymentTransaction tran;
using (PaymentTransactionContext ptc = new PaymentTransactionContext())
{
tran = new PaymentTransaction();
tran.UserSubscriptionHistoryID = sub.UserSubscriptionHistoryID;
tran.UserID = Core.CurrentUserID;
tran.Description = "hidden";
tran.Amount = selectedPackage.Cost;
ptc.Transactions.Add(tran);
c = ptc.SaveChanges(); // c returns 1 row changed, as one row is inserted
if (c == 0)
{
throw new Exception("An unknown error occured");
}
sub.TransactionID = tran.PaymentTransactionID;
c = ushc.SaveChanges(); // c returns 2, as one row is updated, but the duplicate is inserted.
if (c == 0)
{
throw new Exception("An unknown error occured");
}
string success = Core.ResolveServerUrl(Url.Action("validate_payment", "User", new { accountAction = action }));
string cancelled = Core.ResolveServerUrl(Url.Action("cancelled", "User"));
string notification = Core.ResolveServerUrl(Url.Action("Process", "Payment"));
string token = pp.SetExpressCheckout(selectedPackage.Cost.ToString("#.##"), tran.Description, tran.PaymentTransactionID.ToString(), success, cancelled, notification, com.paypal.soap.api.PaymentActionCodeType.Sale, com.paypal.soap.api.CurrencyCodeType.GBP);
if (token != "Failure")
{
tran.VendorToken = token;
ptc.SaveChanges();
return Redirect(string.Format("https://www.{0}paypal.com/webscr?cmd=_express-checkout&token={1}", (PaypalConfiguration.Sandbox ? "sandbox." : ""), token));
}
else
{
ViewBag.Error = "Unable to take your payment, please contact us";
}
}
}
}
}
Core.CurrentUser = null;
return RedirectToActionPermanent("account", new { random = DateTime.Now.Ticks });
}
Пожалуйста, смотрите комментарии после каждого из SaveChanges()
звонков.
Редактировать 2: мне удалось решить эту проблему, выполнив следующие действия, хотя это выглядит не так аккуратно, как раньше:
public ActionResult Payment(int packageID, string action)
{
int c = 0;
using (PackageContext pc = new PackageContext())
{
Package selectedPackage = pc.Packages.Find(packageID);
// store the user's package
UserSubscriptionHistory sub;
using (UserSubscriptionHistoryContext ushc = new UserSubscriptionHistoryContext())
{
sub = new UserSubscriptionHistory();
sub.UserID = Core.CurrentUserID;
sub.PackageID = packageID;
sub.Duration = selectedPackage.Duration;
sub.Cost = selectedPackage.Cost;
ushc.History.Add(sub);
c = ushc.SaveChanges();
}
if (c == 0)
{
throw new Exception("An unknown error occured");
}
// has the user selected a trial package?
if (!selectedPackage.IsTrial.HasValue || !selectedPackage.IsTrial.Value)
{
// get me some money ;)
Paypal pp = new Paypal();
PaymentTransaction tran;
using (PaymentTransactionContext ptc = new PaymentTransactionContext())
{
tran = new PaymentTransaction();
tran.UserSubscriptionHistoryID = sub.UserSubscriptionHistoryID;
tran.UserID = Core.CurrentUserID;
tran.Description = "hidden";
tran.Amount = selectedPackage.Cost;
ptc.Transactions.Add(tran);
c = ptc.SaveChanges();
}
if (c == 0)
{
throw new Exception("An unknown error occured");
}
using (UserSubscriptionHistoryContext ushc = new UserSubscriptionHistoryContext())
{
ushc.History.Attach(sub);
sub.TransactionID = tran.PaymentTransactionID;
c = ushc.SaveChanges();
}
if (c == 0)
{
throw new Exception("An unknown error occured");
}
string success = Core.ResolveServerUrl(Url.Action("validate_payment", "User", new { accountAction = action }));
string cancelled = Core.ResolveServerUrl(Url.Action("cancelled", "User"));
string notification = Core.ResolveServerUrl(Url.Action("Process", "Payment"));
string token = pp.SetExpressCheckout(selectedPackage.Cost.ToString("#.##"), tran.Description, tran.PaymentTransactionID.ToString(), success, cancelled, notification, com.paypal.soap.api.PaymentActionCodeType.Sale, com.paypal.soap.api.CurrencyCodeType.GBP);
if (token != "Failure")
{
using (PaymentTransactionContext ptc = new PaymentTransactionContext())
{
ptc.Transactions.Attach(tran);
tran.VendorToken = token;
ptc.SaveChanges();
}
return Redirect(string.Format("https://www.{0}paypal.com/webscr?cmd=_express-checkout&token={1}", (PaypalConfiguration.Sandbox ? "sandbox." : ""), token));
}
else
{
ViewBag.Error = "Unable to take your payment, please contact us";
}
}
}
Core.CurrentUser = null;
return RedirectToActionPermanent("account", new { random = DateTime.Now.Ticks });
}