Nhibernate通过linq

时间:2016-02-15 03:24:40

标签: c# linq nhibernate

以下是代码,它非常简单。运行此作业每30分钟,它会发现约会(通常最多2个)将约会分配给客户会话。保存约会以使其不再完整,并更新客户会话。

public void CompleteAppointments()
{
    IValidationManager validationManager = new ValidationManager(_repository);
    // Repository starts a new transaction when injected (not shown)
    var appointment = _repository.Query<Appointment>(x => x.EndTime < DateTime.Now && !x.Completed).Take(1).FirstOrDefault();
    while (appointment != null)
    {
        _clientSessionService.SetSessionsForClients(appointment);

        appointment.Completed = true;
        appointment.Clients.Where(c => c.ClientStatus != null && c.ClientStatus.AdminAlerted).ForEachItem(c => c.ClientStatus.AdminAlerted = false);
        validationManager = _saveEntityService.ProcessSave(appointment, validationManager); // validates the input and calls save
        // commits or rollsback the transaction
        validationManager.Finish(); // calls commit or rollback on the session 

        appointment = _repository.Query<Appointment>(x => x.EndTime < DateTime.Now && !x.Completed).Take(1).FirstOrDefault();
    }
}

public virtual void SetSessionsForClients(Appointment apt)
{
    apt.Clients.ForEachItem(x=>SetSessionForClient(x, apt));
}

private void SetSessionForClient(Client client, Appointment apt)
{
    var sessions = client.Sessions.Where(s => !s.SessionUsed && s.AppointmentType == apt.AppointmentType);
    var session = new Session();
    if (sessions.Any())
    {
        session = sessions.OrderBy(s => s.CreatedDate).First();
        session.Appointment = apt;
        session.Trainer = apt.Trainer;
        session.SessionUsed = true;
    }
    else
    {
        session = new Session
        {
            Appointment = apt,
            Trainer = apt.Trainer,
            InArrears = true,
            AppointmentType = apt.AppointmentType,
            SessionUsed = true
        };
        client.AddSession(session);
    }
}

有时,每3天左右,它会做一些非常可怕的事情。 SetSessionForClient的第一行(客户端客户端,Appointment apt)读取

 var sessions = client.Sessions.Where(s => !s.SessionUsed && s.AppointmentType == apt.AppointmentType);

会发生什么,它会返回一个s.SessionUsed == TRUE的会话!因此,它会参加已经与约会相关联的会话,并为其指定一个新约会。覆盖旧的约会完全杀了我的簿记!

我有日志(为了清楚起见,我省略了它们),显示会话,约会和客户端正在更新,然后是同一会话,更新中的同一客户端不同的约会。

我无法理解它,它开始造成严重破坏。通常当我无法看到任何押韵或理由时,我意味着我做了一些可怕的错误。如果您发现可能导致此问题的任何事情,请告诉我。

sql日志显示它为客户端获取所有会话(这不是意料之外的)我已经记录了一个星期左右的sql并且有一次发生。日志显示会话正在更新,SessionUsed值为true。两次。所以可能的嫌疑人名单很短。

1)nhibernate记录sql,但它现在以某种方式在db

上运行

2)nhibernate保存,但在查询时返回并填充对象,但返回的数据是SessionUsed = false,或者只是使用SessionUsed = false

错误地填充对象

3)linq,在调用where(x =&gt;!SessionUsed)时无效。

---编辑---

所以一些好人问我关于我的创建新会话和交易流程。

  • 首先我的存储库调用session.Save
  • 我调用var T = session.BeginTransaction
  • 我尝试T.Commit
  • 如果成功则返回。
  • 如果没有成功调用回滚。
  • 如果回滚运行以下CreateNewCurrentSession

因此,如果提交成功,我就不会创建新会话。我相信我应该这样做。然而,这个应用程序已经生产(虽然轻度使用)约3年,我没有遇到这些问题。我在此之前写的代码更长。所以我不确定会话和交易工作流程是否正确,但是又一次工作了很长时间。

  protected void CreateNewCurrentSession()
    {
        if (CurrentSession != null)
        {
            CurrentSession.Clear();
            CurrentSession.Close();
        }
        if (CurrentStatelessSession != null)
        {
            CurrentStatelessSession.Close();
        }

        var session = SessionFactory.OpenSession();
        // should probably make this value somehow injected or modifyable
        session.FlushMode = FlushMode.Commit;
        CurrentSession = session;
        CurrentStatelessSession = SessionFactory.OpenStatelessSession();

    }

0 个答案:

没有答案