1

次のように定義されたテーブルがあります。

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 ファイルに移動し、データベースから更新を行いました。すべてをインポートしましたが、両方のフィールドを主キーとしてマークしませんでした。2 番目のフィールドを主キーとして追加しようとしましたが、それでも複合として扱われません。

私が抱えている問題は、次のような同様のエントリを持つテーブルで更新を実行するときです。

EntityId = 1、PageType = 'Product'、....および EntityId = 1、PageType = 'Artist'、...

次のようなエラーが表示されます。

同じキーを持つオブジェクトが ObjectStateManager に既に存在します。ObjectStateManager は、同じキーを持つ複数のオブジェクトを追跡できません。

モデルまたはコードでコンポジットを主キーとして適切に使用するにはどうすればよいですか? それとも、これを行うためにある種の複合フィールドを作成する必要がありますか?

アップデート

My Code は 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 に存在するというエラーが発生し続けます。奇妙なことに、DB は適切に更新されているように見えますが、このエラーが発生し続けます。

4

1 に答える 1

0

これはあなたが言及しているものだと思います...

public class CollectionItem
{
    public int CollectionId { get; set; }
    public int ItemId { get; set; }

    [RelatedTo(ForeignKey = "CollectionId")]
    public Collection Collection { get; set; }
    [RelatedTo(ForeignKey = "ItemId")]
    public Item Item { get; set; }
}

そして、モデルビルダーを次のように使用します

var builder = new ModelBuilder();
// ...
builder.Entity<CollectionItem>().HasKey(p=>new {p.CollectionId, p.ItemId});
// ...
model = builder.CreateModel();

これが役立つことを願っています。名前を一般的なものにしようとしました

于 2013-02-27T00:28:57.573 に答える