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
