我有一个这样定义的表:
CREATE TABLE [dbo].[Sitemap](
[EntityId] [int] NOT NULL,
[PageUrl] [nvarchar](400) NOT NULL,
[Frequency] [nvarchar](400) NOT NULL,
[PageType] [nvarchar](400) NOT NULL,
[UpdatedOn] [datetime] NOT NULL,
CONSTRAINT [PK_Sitemap] PRIMARY KEY CLUSTERED
(
[EntityId] ASC,
[PageType] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
我去了我的 edmx 文件并从数据库进行了更新。它导入了所有内容,但没有将两个字段都标记为主键。我尝试将第二个字段添加为主键,但它仍然不会将它们视为组合。
我遇到的问题是当我在具有类似条目的表上运行更新时,例如
EntityId = 1, PageType = 'Product',.... 和 EntityId = 1, PageType = 'Artist',...
我收到一条错误消息:
ObjectStateManager 中已存在具有相同键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。
如何让我的模型或代码正确使用复合作为主键?还是我必须制作某种复合字段才能做到这一点?
更新
我的代码是 NopCommerce 1.90 的一个分支
因此,我添加了一个接口和服务,并将其注册到 IoC 解析器。
对于这个表,我有以下类:
//------------------------------------------------------------------------------
// The contents of this file are subject to the nopCommerce Public License Version 1.0 ("License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.nopCommerce.com/License.aspx.
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
// See the License for the specific language governing rights and limitations under the License.
//
// The Original Code is nopCommerce.
// The Initial Developer of the Original Code is NopSolutions.
// All Rights Reserved.
//
// Contributor(s): _______.
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using NopSolutions.NopCommerce.BusinessLogic.CustomerManagement;
using NopSolutions.NopCommerce.BusinessLogic.Infrastructure;
using NopSolutions.NopCommerce.BusinessLogic.Payment;
using NopSolutions.NopCommerce.BusinessLogic.Promo.Affiliates;
using NopSolutions.NopCommerce.BusinessLogic.Promo.Discounts;
using NopSolutions.NopCommerce.BusinessLogic.Shipping;
using NopSolutions.NopCommerce.BusinessLogic.Tax;
namespace NopSolutions.NopCommerce.BusinessLogic.SEO.Sitemaps
{
/// <summary>
/// Represents a Sitemap
/// </summary>
[Serializable]
public partial class Sitemap : BaseEntity
{
#region Utilities
#endregion
#region Properties
/// <summary>
/// Gets or Sets EntityId (Product ID, Show ID, etc.)
/// </summary>
public int EntityId { get; set; }
/// <summary>
/// Gets or sets the Page Url
/// </summary>
public string PageUrl { get; set; }
/// <summary>
/// Gets of set the Page Frequency (Should be one of the following - Always, Hourly, Daily, Weekly, Monthly, Yearly, Never)
/// </summary>
public string Frequency { get; set; }
/// <summary>
/// Gets or sets the page type. For example: Product, or Show
/// </summary>
public string PageType { get; set; }
/// <summary>
/// Gets or sets the date and time of sitemap entry update
/// </summary>
public DateTime UpdatedOn { get; set; }
#endregion
}
}
然后我有接口和服务:
界面:
//------------------------------------------------------------------------------
// The contents of this file are subject to the nopCommerce Public License Version 1.0 ("License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.nopCommerce.com/License.aspx.
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
// See the License for the specific language governing rights and limitations under the License.
//
// The Original Code is nopCommerce.
// The Initial Developer of the Original Code is NopSolutions.
// All Rights Reserved.
//
// Contributor(s): _______.
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using NopSolutions.NopCommerce.BusinessLogic.CustomerManagement;
using NopSolutions.NopCommerce.BusinessLogic.Payment;
using NopSolutions.NopCommerce.BusinessLogic.Shipping;
using NopSolutions.NopCommerce.Common;
namespace NopSolutions.NopCommerce.BusinessLogic.SEO.Sitemaps
{
/// <summary>
/// Sitemap service
/// </summary>
public partial interface ISiteMapService
{
/// <summary>
/// Gets a Sitemap entry based on url.
/// </summary>
/// <param name="url">Fully Qualified URL (e.g. http://www.onlinesheetmusic.com/default.aspx)</param>
/// <returns></returns>
Sitemap GetSitemap(string url);
/// <summary>
/// Gets the most recent entry to the sitemap table
/// </summary>
/// <returns></returns>
Sitemap GetLastAddedSitemap(string pageType);
/// <summary>
/// Gets a list of Sitemap entries that are in the init state of the given Page Type
/// </summary>
/// <param name="pageType">Page Type</param>
/// <returns></returns>
List<Sitemap> GetInitEntries(string pageType);
/// <summary>
/// Bool to determine if a given pageType has any entries in the init state.
/// </summary>
/// <param name="pageType"></param>
/// <returns></returns>
bool IsInit(string pageType);
void InitSitemap(string pageType, int startProdId = 0);
/// <summary>
/// Inserts a sitemap entry
/// </summary>
/// <param name="order">Order</param>
void InsertSitemap(Sitemap sm);
/// <summary>
/// Updates the order
/// </summary>
/// <param name="order">The order</param>
void UpdateSitemap(Sitemap sm);
}
}
服务:
//------------------------------------------------------------------------------
// The contents of this file are subject to the nopCommerce Public License Version 1.0 ("License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.nopCommerce.com/License.aspx.
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
// See the License for the specific language governing rights and limitations under the License.
//
// The Original Code is nopCommerce.
// The Initial Developer of the Original Code is NopSolutions.
// All Rights Reserved.
//
// Contributor(s): _______.
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using NopSolutions.NopCommerce.BusinessLogic.Audit;
using NopSolutions.NopCommerce.BusinessLogic.Caching;
using NopSolutions.NopCommerce.BusinessLogic.Configuration.Settings;
using NopSolutions.NopCommerce.BusinessLogic.CustomerManagement;
using NopSolutions.NopCommerce.BusinessLogic.Data;
using NopSolutions.NopCommerce.BusinessLogic.Directory;
using NopSolutions.NopCommerce.BusinessLogic.Infrastructure;
using NopSolutions.NopCommerce.BusinessLogic.Localization;
using NopSolutions.NopCommerce.BusinessLogic.Messages;
using NopSolutions.NopCommerce.BusinessLogic.Messages.SMS;
using NopSolutions.NopCommerce.BusinessLogic.Payment;
using NopSolutions.NopCommerce.BusinessLogic.Products;
using NopSolutions.NopCommerce.BusinessLogic.Products.Attributes;
using NopSolutions.NopCommerce.BusinessLogic.Profile;
using NopSolutions.NopCommerce.BusinessLogic.Promo.Discounts;
using NopSolutions.NopCommerce.BusinessLogic.QuickBooks;
using NopSolutions.NopCommerce.BusinessLogic.Security;
using NopSolutions.NopCommerce.BusinessLogic.Shipping;
using NopSolutions.NopCommerce.BusinessLogic.Tax;
using NopSolutions.NopCommerce.Common;
using NopSolutions.NopCommerce.Common.Extensions;
using NopSolutions.NopCommerce.Common.Utils;
using NopSolutions.NopCommerce.Common.Utils.Html;
namespace NopSolutions.NopCommerce.BusinessLogic.SEO.Sitemaps
{
/// <summary>
/// Sitemap service
/// </summary>
public partial class SiteMapService : ISiteMapService
{
#region Fields
/// <summary>
/// Object context
/// </summary>
private readonly NopObjectContext _context;
/// <summary>
/// Cache service
/// </summary>
private readonly ICacheManager _cacheManager;
#endregion Fields
#region Ctor
/// <summary>
/// Ctor
/// </summary>
/// <param name="context">Object context</param>
public SiteMapService(NopObjectContext context)
{
this._context = context;
this._cacheManager = new NopRequestCache();
}
#endregion Ctor
#region Utilities
#endregion Utilities
#region Methods
/// <summary>
/// Gets a sitemap entry
/// </summary>
/// <param name="url">The url of the sitempa item</param>
/// <returns>Order</returns>
public Sitemap GetSitemap(string url)
{
if (!url.IsNotNullOrEmpty())
return null;
var query = from sm in _context.Sitemaps
where sm.PageUrl.Contains(url)
select sm;
var sitemap = query.SingleOrDefault();
return sitemap;
}
public Sitemap GetLastAddedSitemap(string pageType)
{
var query = (from sm in _context.Sitemaps
where sm.PageType.Equals(pageType)
orderby sm.UpdatedOn descending
select sm).Take(1);
var sitemap = query.SingleOrDefault();
return sitemap;
}
public List<Sitemap> GetInitEntries(string pageType)
{
var query = (from sm in _context.Sitemaps
where sm.PageType.Equals(pageType)
&& sm.Frequency == "Init"
select sm).Take(500);
return query.ToList();
}
/// <summary>
/// Bool to check if a given type has any entries in the init state.
/// </summary>
/// <param name="pageType">Page Type</param>
/// <returns>True or False</returns>
public bool IsInit(string pageType)
{
var query = (from sm in _context.Sitemaps
where sm.PageType.Equals(pageType)
&& sm.PageUrl.Equals("Init")
select sm).Take(1);
if (query == null)
return true;
else
return false;
}
public void InitSitemap(string pageType, int startProdId = 0)
{
_context.Sp_SitemapInit(pageType, startProdId);
}
/// <summary>
/// Inserts a sitemap entry
/// </summary>
/// <param name="sm">Sitemap Entry to Insert</param>
public void InsertSitemap(Sitemap sm)
{
if (sm == null)
throw new ArgumentNullException("sitemap");
sm.PageUrl = CommonHelper.EnsureNotNull(sm.PageUrl);
sm.PageType = CommonHelper.EnsureNotNull(sm.PageType);
sm.Frequency = CommonHelper.EnsureNotNull(sm.Frequency);
_context.Sitemaps.AddObject(sm);
_context.SaveChanges();
}
/// <summary>
/// Updates a sitemap entry
/// </summary>
/// <param name="sm">Sitemap Entry to update</param>
public void UpdateSitemap(Sitemap sm)
{
if (sm == null)
throw new ArgumentNullException("sitemap");
sm.PageUrl = CommonHelper.EnsureNotNull(sm.PageUrl);
sm.PageType = CommonHelper.EnsureNotNull(sm.PageType);
sm.Frequency = CommonHelper.EnsureNotNull(sm.Frequency);
if(_context.Sitemaps.Any(s => (s.PageUrl == sm.PageUrl || s.EntityId == sm.EntityId)))
{
if (!_context.IsAttached(sm))
_context.Sitemaps.Attach(sm);
}
else
{
_context.Sitemaps.AddObject(sm);
}
_context.SaveChanges();
}
#endregion Methods
#region Properties
/// <summary>
/// Gets a value indicating whether cache is enabled
/// </summary>
public bool CacheEnabled
{
get
{
return IoC.Resolve<ISettingManager>().GetSettingValueBoolean("Cache.OrderManager.CacheEnabled");
}
}
#endregion Properties
}
}
当我打电话
var sitemapservice = IoC.Resolve<ISiteMapService>();
sitemapservice.InitSitemap("Artist");
var smEntries = sitemapservice.GetInitEntries("Artist");
foreach (Sitemap sm in smEntries)
{
using (MvcMiniProfiler.MiniProfiler.StepStatic("Processing Entry: " + sm.EntityId + "," + sm.PageType))
{
sm.Frequency = "Monthly";
sm.PageUrl = SEOHelper.GetUrl(this.ArtistService.GetArtistById(sm.EntityId), this.SettingManager.StoreUrl);
using (MvcMiniProfiler.MiniProfiler.StepStatic("Updating database"))
{
sitemapservice.UpdateSitemap(sm);
}
curCount++;
}
}
它应该获取 init 阶段的所有条目并使用正确的 url 设置它们,但无论出于何种原因,我不断收到错误消息,说 ObjectStateManager 中已经存在具有相同键的对象。虽然奇怪的是数据库似乎正在正确更新,但它一直给我这个错误。