在NHibernate中不使用映射连接表

本文关键字:映射 连接 NHibernate | 更新日期: 2023-09-27 18:05:22

我有以下两个对象:

用户

class User {
    public int role;
}

class Role {
    public int id;
    public string name;
}

请注意,User中的role属性是int而不是Role,这是我们的局限性。

我想在所有用户和他的每个角色之间进行连接。在映射对象中,你可以理解没有引用,只有一个简单的类型(int)。

如何执行join语句?

在NHibernate中不使用映射连接表

这叫做theta join:

var a = (from u in session.Query<User>()
        from r in session.Query<Role>()
        where u.role == r.id
        select new { u.Username, Role = r.name }).ToList();

假设在User类中有一个Username属性

是的,这个" θ连接"(我刚学会这个术语)非常方便,我们不用担心放入无意义的映射关系。

警告,但是在使用这个!!这让我犯了很多错。

加上上面的例子…

var list = new List<int>( { 2, 3 } ); // pretend in-memory data from something.
var a = 
   (from u in session.Query<User>()
    from x in list
    from r in session.Query<Role>()
    where u.role == r.id
    where r.id == x.id  // pretend list wants to limit to only certain roles.
    select new { u.Username, Role = r.name }).ToList();

这将爆炸一些不支持的异常。诀窍在于任何来自NHibernate Session的东西都必须是LAST。所以这个修改将工作:

var a = 
   (from x in list
    from u in session.Query<User>()
    from r in session.Query<Role>()
    where u.role == r.id
    where r.id == x.id  // pretend list wants to limit to only certain roles.
    select new { u.Username, Role = r.name }).ToList();

顺便说一句,你也可以使用join,但是你必须确保如果你有任何可空数据类型,如果你要连接到不可空的东西,你要使用。value。

var a = 
   (from x in list
    from u in session.Query<User>()
    join r in session.Query<Role>() on u.role equals r.id
    where r.id == x.id  // pretend list wants to limit to only certain roles.
    select new { u.Username, Role = r.name }).ToList();

说到这里,假设你有一个方法它有一些动态条件。在这个例子中,"list"可能是要筛选的角色列表,但如果列表不存在,则根本不进行筛选。好吧,如果您执行.ToList(),那么您将导致该查询立即执行。但是,您可以添加一个条件,然后稍后执行:

var a = 
    from u in session.Query<User>()
    join r in session.Query<Role>() on u.role equals r.id
    where r.id == x.id  // pretend list wants to limit to only certain roles.
    select new { u.Username, Role = r.name, RoleID = r.id }; // Adding the Role ID into this output.
if (list != null) // assume if the list given is null, that means no filter.
{
    a = a.Where(x => list.Contains(x.RoleID));
    // WARNING. Unfortunately using the "theta" format here will not work. Not sure why.
}
var b = a.ToList(); // actually execute it.
var c = a.Select(x => new { x.Username, x.Role }).ToList() // if you insist on removing that extra RoleID in the output.
最后一件事……有时一些简单的逻辑在select new { .. }部分执行时会失败。我无法解释。在我们的例子中,逻辑只是将一个int的DB值转换为一个模型的Enumerator。但为了解决这个问题,我只是在读取数据时避免进行转换,但保存了值。然后在后面的步骤中,在加载数据之后,我在另一个LINQ语句中进行转换。

免责声明:虽然我在过去的几个星期里写了很多这样的东西,但我并没有把这些代码放入我的编译器中进行100%的验证。