【发布时间】:2012-03-14 18:55:40
【问题描述】:
真的希望有人能提供帮助,因为过去两个晚上我一直在梳理头发,而且速度不快!并且拼命地试图让一个家庭项目进行下去,而我这样做是为了不赚钱,并且在我试图用它来学习一些新技术时,它迅速占用了我的时间。
这似乎是一个常见问题,因为在 stackoverflow 等上发现了一些类似的 ish 帖子,但现在似乎已经引导我找到了一个可行的解决方案。
我得到错误或重复的行进入数据库,我的简化模型是一对多的关系。但我试图将 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; }
}
然后我的代码如下,稍微复杂一点,但希望能明白。请注意,数据上下文存储在 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();
}
基本上应该发生的情况是有人浏览了一个页面,调用 LogStockPageView() 进而从会话、数据库中获取一个 WebsiteUserSession 实体或创建一个新实体。然后将 WebsitePageTracking 实体添加到与 WebsiteUserSession 关联的数据库中。
你可以看到所有试图让它工作的注释行,但我要么得到错误,要么插入了很多重复的行:(
这样的错误之一是“ObjectStateManager 中已存在具有相同键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。”。
请有人看看我哪里出错了,甚至可以提出更好的解决方案吗?真的很想与 EF 合作,但很挣扎:(
谢谢,卡尔
【问题讨论】:
标签: c# entity-framework entity-framework-4 ado.net