0

Suppose I have the following class with Many-To-Many relationship to itself:

public class A
{
    public int Id { get; set; }
    public string Title { get; set; }
    public ICollection<A> Requires{ get; set; }
    public ICollection<A> Blocks{ get; set; }
}

From this answer I understood that I need to change my class in the following way in order to achieve the relationship:

public class A
{
    public int Id { get; set; }
    public string Title { get; set; }
    public ICollection<ARelation> Requires{ get; set; }
    public ICollection<ARelation> Blocks{ get; set; }
}

public class ARelation
{
    public int BlockedId { get; set; }
    public int RequiredId{ get; set; }
    public virtual A Blocked { get; set; }
    public virtual A Required{ get; set; }
}

And configuration file:

modelBuilder.Entity<ARelation>()
            .HasKey(e => new { e.BlockedId, e.RequiredId });

modelBuilder.Entity<ARelation>()
            .HasOne(e => e.Blocked)
            .WithMany(e => e.Requires)
            .HasForeignKey(e => e.BlockedId);

modelBuilder.Entity<ARelation>()
            .HasOne(e => e.Required)
            .WithMany(e => e.Blocks)
            .HasForeignKey(e => e.RequiredId);

And until here it's all fine.

My problem is that I haven't find a proper example on how to do CRUD operations.

For example, suppose I want to store a new A object, I would use the following operations:

var item = new A{
   Title = "Test"
}
_context.AObjects.Add(item);
await _context.SaveChangesAsync();

Now suppose I want to add a new A object that requires the previously created object, what is the procedure I should follow?

Example of how a GetAll result should look like approximately:

 [{
   Title: "Test"
   Blocks: [{
        Title: "Test2"
   }]
 },
 { 
   Title: "Test2"
   Requires: [{
        Title: "Test"
   }]
 }]

Do I need to create the object ARelation or is it created automatically?

Can someone provide an example of the operation?

GioGio
  • 448
  • 2
  • 5
  • 22

1 Answers1

0

Assume you have added some A object:

Id  Title
1   Test
2   Test2
3   hello
4   world

You could use below code to add Requires and Blocks when creating a new A object:

var item = new A
        {
            Title = "TestAgain",
            Blocks = new List<ARelation>()
            {
                new ARelation()
                {
                    BlockedId = 1
                },
                new ARelation()
                {
                    BlockedId = 2
                }
            },
            Requires = new List<ARelation>()
            {
                new ARelation()
                {
                    RequiredId = 3
                },
                new ARelation()
                {
                    RequiredId = 4
                }
            }
        };
        _context.AObjects.Add(item);
        await _context.SaveChangesAsync();

When you want to get all A objects and show their titles only, you could use Include and ThenInclude with Select method:

[HttpGet]
public ActionResult GetAll()
    {
       var x =  _context.AObjects
                        .Include(a => a.Requires)
                               .ThenInclude(r => r.Required)
                        .Include(a => a.Blocks)
                                .ThenInclude(b => b.Blcoked)
                        .Select(a => new 
                    {
                        Title = a.Title,
                        Requires = a.Requires.Select(r => new { Title = r.Required.Title}).ToList(),
                        Blocks = a.Blocks.Select(r => new { Title = r.Blocked.Title }).ToList()
                    }).ToList();


        return new JsonResult(x);
    }

Result:

 [{
    "title": "TestAgain",
    "requires": [
        {
            "title": "hello"
        },
        {
            "title": "world"
        }
    ],
    "blocks": [
        {
            "title": "Test"
        },
        {
            "title": "Test2"
        }
    ]
},
{...}]
Ryan
  • 19,118
  • 10
  • 37
  • 53