Skip to content

One to One constrained relation with PropertyRef causes N+1 #3292

Closed
@Madajevas

Description

@Madajevas

Consider code bellow:

private ISessionFactory sessionFactory;

[SetUp]
public void SetUp()
{
    var config = Fluently.Configure()
        .Database(MsSqlConfiguration.MsSql2008.ConnectionString("Server=localhost;Database=test;User Id=sa;Password=Test4000;"))
        .Mappings(m => m.FluentMappings.AddFromAssemblyOf<NPlusOneWithQueryButNotQueryOver>())
        .BuildConfiguration();

    sessionFactory = config.BuildSessionFactory();
}

[Test]
public void Query()
{
    using var session = sessionFactory.OpenSession(new LoggingInterceptor());

    var entities = session.Query<EntityOne>().ToList();
}

public class EntityOne
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual EntityTwo EntityTwo { get; set; }
}

public class EntityTwo
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual EntityOne EntityOne { get; set; }
}

public class EntityOneMap : ClassMap<EntityOne>
{
    public EntityOneMap()
    {
        Id(e => e.Id).GeneratedBy.Identity();
        Map(e => e.Name);
        HasOne(e => e.EntityTwo)
            .PropertyRef(x => x.EntityOne)
            .Constrained()
            .LazyLoad()
            .Cascade.Delete()
            .Not.ForeignKey();
    }
}

public class EntityTwoMap : ClassMap<EntityTwo>
{
    public EntityTwoMap()
    {
        Id(e => e.Id).GeneratedBy.Identity();
        Map(e => e.Name);
        References(e => e.EntityOne)
            .Unique()
            .Not.Nullable();
    }
}

public class LoggingInterceptor : EmptyInterceptor
{
    public override SqlString OnPrepareStatement(SqlString sql)
    {
        Console.WriteLine(sql);

        return sql;
    }
}

With schema and data:

drop table if exists EntityOne;
create table EntityOne (
	id int primary key,
	name varchar(10)
);

drop table if exists EntityTwo;
create table EntityTwo (
	id int primary key,
	EntityOne_id int not null,
	name varchar(10)
);

insert into EntityOne values (1, 'e1_1'), (2, 'e1_2'), (3, 'e1_3');
insert into EntityTwo values (4, 1, 'e2_1'), (5, 2, 'e2_2'), (6, 3, 'e2_3');

When test is executed, four queries can be found in test output: one to retrieve records from "EntityOne" table, and three queries for each "EntityTwo".
If .PropertyRef(x => x.EntityOne) is removed, only one query is made. And now, if .Fetch(e => e.EntityTwo) is added, query with join clause is made, however joins are happening on id fields, not EntityOne.Id = EntityTwo.EntityOne_id.

Is this how .Constrined() with .PropertyRef() supposed to work? If so, can limitation not be able join on specified field be explained?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions