Relationships in XPO

I’m replying to a post in the DevExpress XPO forum, where the question came up of how to use joins with XPO/LINQ and projection. Unfortunately, the forum system mangled my code snippets, so I thought I’d put the info up here as well.

Emilio Garcia wrote: I trying to create a linq query to retrive some objects, this is the query:

var
listadoSesiones = from u in usuariosjoin s in sesiones on u.ObjId equals
s.UsuarioIdwhere s.Activa == true
orderby s.FechaInicio ascending
select new { u.NombreUsuario, u.NombreCompleto, s.FechaInicio, s.FechaFin };

I’m pretty sure this doesn’t have anything to do with the Guid type. Instead, the problem is the projection you’re trying to do. Instead, you should define your classes correctly and things should be much easier… I’m roughly translating your names, and I’m coming up with classes that look like this:

public class User: XPObject {
  public User(Session session) : base(session) { }

  private string userName;
  public string UserName {
    get { return userName; }
    set { SetPropertyValue("UserName", ref userName, value); }
  }

  private string fullName;
  public string FullName {
    get { return fullName; }
    set { SetPropertyValue("FullName", ref fullName, value); }
  }

  [Association("User-Sessions")]
  public XPCollection Sessions {
    get { return GetCollection("Sessions"); }
  }
}

public class LoginSession: XPObject {
  public LoginSession(Session session) : base(session) { }

  private DateTime startTime;
  public DateTime StartTime {
    get { return startTime; }
    set { SetPropertyValue("StartTime", ref startTime, value); }
  }

  private DateTime endTime;
  public DateTime EndTime {
    get { return endTime; }
    set { SetPropertyValue("EndTime", ref endTime, value); }
  }

  private bool active;
  public bool Active {
    get { return active; }
    set { SetPropertyValue("Active", ref active, value); }
  }

  private User user;
  [Association("User-Sessions")]
  public User User {
    get { return user; }
    set { SetPropertyValue("User", ref user, value); }
  }
}

Note the two properties marked with [Association] – these are the ones that implement the relationship for XPO. You should always set these relationships up correctly, then it will be much easier to get to the right data. (As an aside – when working with legacy databases, you’ll sometimes need to use the [Persistent(...)] attribute on properties like this to define the name of the foreign key fields in your database.) Once you’ve got your classes set up like this, you can easily query the information you were looking for, utilizing these pre-configured relationships:

using (UnitOfWork unitOfWork = new UnitOfWork( )) {
  var activeSessions =
    from s in new XPQuery<LoginSession>(unitOfWork)
    where s.Active
    orderby s.StartTime
    select new {
      s.User.UserName,
      s.User.FullName,
      s.StartTime,
      s.EndTime // why this? session is active, no end time...
    };
  foreach (var session in activeSessions)
    Console.WriteLine("Username: {0}, Full name: {1}, Start time: {2}",
      session.UserName, session.FullName, session.StartTime);
}

Of course on the other hand there’s no real need to do this either – it’s so easy to get to the data you need through the relationship properties, you don’t need to work with projection.

Sorry, this blog does not support comments.

I used various blog hosting services since this blog was established in 2005, but unfortunately they turned out to be unreliable in the long term and comment threads were lost in unavoidable transitions. At this time I don't want to enable third-party services for comments since it has become obvious in recent years that these providers invariably monetize information about their visitors and users.

Please use the links in the page footer to get in touch with me. I'm available for conversations on Keybase, Matrix, Mastodon or Twitter, as well as via email.