本当に誰かが助けてくれることを願っています。私が何か新しい技術を学ぶためにそれを使用しようとしているので、私が無益にしている家族計画を進めることが必死になっています。EF 4.3セービングエラーが発生したり、行が重複したりする
これはよくある問題で、stackoverflowなどのいくつかの類似したish投稿を見つけたようですが、現在は私を実際の解決策に導いているようです。
データベースにエラーや重複行が発生すると、私の単純化モデルは1対多の関係になります。しかし、すべてのページの読み込み時にデータベースヒットを保存するために、ユーザーセッションにWebsiteUserSessionオブジェクトを格納しようとしています。
モデル:
public class WebsitePageTracking
{
[Key]
public long Id { get; set; }
public virtual WebsiteUserSession WebsiteUserSession { get; set; }
public DateTime DateTime { get; set; }
public string TrackUrl { get; set; }
}
public class WebsiteUserSession
{
[Key]
public long Id { get; set; }
public Guid Guid { get; set; }
public string IpAddress { get; set; }
public DateTime DateTime_Created { get; set; }
public DateTime DateTime_LastSessionStart { get; set; }
public virtual ICollection<WebsitePageTracking> WebsitePageTracking { get; set; }
}
次に、以下のように私のコードは、もう少し複雑ですが、うまくいけば、アイデアを得ます。 datacontextは、1つの提案であったHttpContext.Itemsに格納されていることに注意してください。
/// <summary>
/// public method for fetching and persisting website user session
/// </summary>
/// <returns></returns>
public static WebsiteUserSession GetWebsiteUserSession()
{
// set initial variables
Guid? websiteUserGuid = null;
string websiteUserIpAddress = HttpContext.Current.Request.UserHostAddress;
WebsiteUserSession websiteUserSession = null;
// first try and get from the session
if (HttpContext.Current.Session["WebsiteUserSession"] != null)
{
// load the website user session, and fetch out the guid
websiteUserSession = HttpContext.Current.Session["WebsiteUserSession"] as WebsiteUserSession;
websiteUserGuid = websiteUserSession.Guid;
// check to see if ip has changed, if so drop website user session
if (websiteUserSession.IpAddress != websiteUserIpAddress)
websiteUserSession = null;
}
else
{
// nothing so create brand new guid
websiteUserGuid = Guid.NewGuid();
}
// if we don't have one which came from the session then get the website user session using guid/ip
if (websiteUserSession == null)
websiteUserSession = GetWebsiteUserSession((Guid)websiteUserGuid, websiteUserIpAddress);
// if not stored in the session add that now
if (HttpContext.Current.Session["WebsiteUserSession"] == null)
HttpContext.Current.Session.Add("WebsiteUserSession", websiteUserSession);
// return back website user session object
return websiteUserSession;
}
/// <summary>
/// gets or creates a website user session record in the database
/// </summary>
/// <param name="guid">guid generated for the website user</param>
/// <param name="ipAddress">public ip address of website user</param>
/// <returns></returns>
private static WebsiteUserSession GetWebsiteUserSession(Guid guid, string ipAddress)
{
DataContext dataContext = HttpContext.Current.Items["DataContext"] as DataContext;
// try and fetch a user session from database
WebsiteUserSession websiteUserSession = dataContext
.WebsiteUserSessions
.Where(x => x.Guid == guid && x.IpAddress == ipAddress)
.SingleOrDefault();
if (websiteUserSession != null)
{
// if found update last session time
websiteUserSession.DateTime_LastSessionStart = DateTime.Now;
}
else
{
// create a new website user session
websiteUserSession = new WebsiteUserSession();
websiteUserSession.Guid = guid;
websiteUserSession.IpAddress = ipAddress;
websiteUserSession.DateTime_Created = websiteUserSession.DateTime_LastSessionStart = DateTime.Now;
dataContext.WebsiteUserSessions.Add(websiteUserSession);
}
// persist changes
dataContext.SaveChanges();
return websiteUserSession;
}
/// <summary>
/// log a stock page view to database
/// </summary>
/// <param name="stockId">id of stock being viewed</param>
public static void LogStockPageView(int stockId)
{
DataContext dataContext = HttpContext.Current.Items["DataContext"] as DataContext;
WebsiteUserSession websiteUserSession = GetWebsiteUserSession();
//dataContext.WebsiteUserSessions.Attach(websiteUserSession);
//dataContext.Entry(websiteUserSession).State = EntityState.Unchanged;
WebsitePageTracking pageTrack = new WebsitePageTracking();
pageTrack.WebsiteUserSession = websiteUserSession;
pageTrack.DateTime = DateTime.Now;
pageTrack.TrackUrl = HttpContext.Current.Request.Url.ToString();
dataContext.Entry(client).State = EntityState.Unchanged;
dataContext.Entry(website).State = EntityState.Unchanged;
dataContext.Entry(websiteUserSession).State = EntityState.Unchanged;
//dataContext.Entry(websiteUserSession.WebsitePageTracking).State = EntityState.Detached;
//dataContext.WebsiteUserSessions.Attach(pageTrack.WebsiteUserSession);
dataContext.WebsitePageTracking.Add(pageTrack);
//dataContext.Entry(pageTrack.WebsiteUserSession).State = EntityState.Unchanged;
dataContext.SaveChanges();
}
は、基本的に何が起こるべきことは、誰かが順番にいずれかのセッション、データベースからWebsiteUserSessionのエンティティを取得するか、新しいものを作成し、呼び出されるページ、LogStockPageViewを()閲覧しています。次に、WebsitePageTrackingエンティティがWebsiteUserSessionへの関連付けとともにデータベースに追加されます。
あなたはこの作業を取得しようとする試みのすべてのコメント行を見ることができますが、私は挿入されている重複行のエラーや多くを得るのいずれか:(
一つのそのようなエラーは、同じキーを持つオブジェクトが既に存在する」これですObjectStateManagerで同じキーを持つ複数のオブジェクトを追跡することはできません」。
(英語の場合は、実際にEFを使用していますが、ありがとう、Carl
他のエンティティを参照しているサンプルコードで申し訳ありませんが、私の間違いを簡略化しましたが、いくつかのビットを外すのを忘れました。とにかく私はあなたの提案された変更を行い、それは動作します!今日はニュージーランドの深夜過ぎですので、寝る必要がありましたが、あなたの提案を試してみたいと思っていました...明日もう一度、詳細に行き、私のプロジェクトを続けるでしょう:)ありがとう100万!! – user1259167