Let's assume that you configured the Task model into database context the right way. As a side note, I would give it another name.
public class Task
{
public int Id { get; set; }
public string Name { get; set; }
public int Position { get; set; }
public int? NextId { get; set; }
public int? PreviousId { get; set; }
public Task Next { get; set; }
public Task Previous { get; set; }
}
public class Context : DbContext
{
private const string DefaultConnectionString = "Data Source=(localdb)\\MSSQLLocalDB; Initial Catalog = LinkedList";
public DbSet<Task> Tasks { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(DefaultConnectionString);
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Task>().ToTable("Tasks");
modelBuilder.Entity<Task>()
.HasOne(t => t.Next)
.WithOne(t => t.Previous)
.HasForeignKey(typeof(Task), "NextId")
.OnDelete(DeleteBehavior.NoAction);
modelBuilder.Entity<Task>()
.HasOne(t => t.Previous)
.WithOne(t => t.Next)
.HasForeignKey(typeof(Task), "PreviousId")
.OnDelete(DeleteBehavior.NoAction);
}
}
Moving on, you could do something like this
var first = context.Tasks.FirstOrDefault(t => t.Position == 1);
var second = context.Tasks.FirstOrDefault(t => t.Position == 2);
if (first is not null && second is not null)
{
var newTask = new Task()
{
Name = "Third Task ",
Position = 3,
NextId = second.Id,
PreviousId = first.Id
};
context.Tasks.Add(newTask);
context.SaveChanges();
first.Next = newTask;
newTask.Next = second;
context.SaveChanges();
}
After creating newTask it should be marked as Added. This can be achieved either by directly modifying its state or by placing it on the contexts DbSet. Next, you should commit the transaction (it is important to avoid a circular reference) and then re-establish the pointed entries for the Next and Previous navigation properties. After that, you can commit the transaction again.
This should be the final result
