Skip to content

Using Reference.OneToOne to maintain the FK field in the model with Fluent mapping causes cycles and memory leak #637

@ilya-at-prettyneat

Description

@ilya-at-prettyneat

Greetings.

Given these models:

public class OwnedThingie
{
	public long Id {get;set;}
	public long OwnerId {get;set;}
	public UserMan Owner {get;set;}
}

public class UserMan
{
	public long Id {get;set;}
	public string Name {get;set;}
	public List<OwnedThingie> Thingies {get;set;}
}

and these mappings:

For<OwnedThingie>()
	.TableName("DbThingies")
	.PrimaryKey(o => o.Id, true)
	.Columns
	(
		c => 
		{
			c.Column(o => o.Id);
			c.Column(o => o.OwnerId);
			c.Column(o => o.Owner).WithName("OwnerId").Reference( um => um.Id, ReferenceType.OneToOne )
		},
		true
	);

For<UserMan>()
	.TableName("DbUsers")
	.PrimaryKey(u => u.Id, true)
	.Columns
	(
		c => 
		{
			c.Column(u => u.Id);
			c.Column(u => u.Name);
			c.Many(u => u.Thingies).Reference(o => o.OwnerId)
		},
                true
	);

This will create a gigantic memory leak as it will not recognize the owner <-> thingies as a looping relationship.

Our objective
We need to have both the column OwnerId and the property Owner on the data model.
OneToOne used to be the way to go, but unfortunately if you then want to establish proper relationships it will eat all of your memory - so much that the Heap display will mark a bunch of places as [Cycled].
(our actual app model has 17 tables mapped and spikes around 3GB of usage just for the NPOCO-powered service).

Proposed Solutions

  • Make a ForeignObjectOnly enum option which will leave to the coder the ability to declare the FK fields and throw otherwise
  • Make OneToOne recognize looping relationships with Many
  • ...perhaps there is a simple solution we are missing?

Tried:

  • Conditionally stopping it from including too many nested layers in the map. Failed.
  • Using .Result and .Computed to overcome the limitation on same-field-name. Failed.
  • Creating a different model that contained generic objects instead of actual data objects to stop the join propagation. Failed.
  • Switching everything to Foreign and pretending the FK properties are still there. Failed.

Any suggestions are extremely welcome.

Using NPoco latest, SQL Server 2019, .NET Core currently at 3.1.latest

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions