'stop tracking child property in asp.net core entity framework

I have the following classes in my data folder

public class A
{
    public int Id { get; set; }
    [InverseProperty("A")]
    public IList<B> Bs{ get; set; }
}

public class B
{
    public int Id { get; set; }
    
    public int? A_FK { get; set; }
    [ForeignKey("A_FK")]
    public A A{ get; set; }
    
    public int? C_FK { get; set; }
    [ForeignKey("C_FK")]
    public C { get; set; }
}

public class C
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Code1 { get; set; }
    public string Code2 { get; set; }
    public string Code3 { get; set; }
}

In my view code:

<table id="" class="table table-striped table-bordered" style="width:100%" data-idcounter="0">
    <thead>
        <tr>
            <th style="width:20px;"></th>
            <th> Code1 </th>
            <th> Code2 </th>
            <th> Code3 </th>
        </tr>
    </thead>
    <tbody>
        @if (Model.A != null)
            if (Model.A.Bs != null)
                for (int Index = 0; Index < Model.A.Bs.Count; Index++)
                {
                    if (Model.A.Bs[Index].C.Code1 != "1") continue;
                    <tr>
                        <td rowspan="2">
                            <div class="removeA" style="color:red;text-align:center;">
                                <i class="fa fa-minus"></i>
                            </div>
                        </td>
                        <td>
                            @{
                                var Code1Items = new SelectList(((List<C>)ViewData["A"]).Where(x => x.Code2 == null), "Code1", "Name");
                                var Code2Items = new SelectList(((List<C>)ViewData["A"])
                                    .Where(x => x.Code2 != null && x.Code3 == null && x.Code1 == Model.A.Bs[Index].C.Code1)
                                    , "Code2", "Name");
                                var Code3Items = new SelectList(((List<C>)ViewData["A"])
                                    .Where(x => x.Code2 != null && x.Code3 != null && x.Code2 == Model.A.Bs[Index].C.Code2)
                                    , "Code3", "Name");
                            }
                            <select asp-for="A.Bs[Index].C.Code1" asp-items="Code1Items" class="form-control">
                            </select>
                        </td>
                        <td>
                            <select asp-for="A.Bs[Index].C.Code2" asp-items="Code2Items" class="form-control">
                                <option value="0">--- Choose ---</option>
                            </select>
                        </td>
                        <td>
                            <select asp-for="A.Bs[Index].C.Code3" asp-items="Code3Items" class="form-control">
                                <option value="0">--- Choose ---</option>
                            </select>
                        </td>
                    </tr>
                }
    </tbody>
    <tfoot>
        <tr>
            <td colspan="5">
                <a id="addA" class="btn border-primary" href="javascript:;">
                    <i class="fa fa-plus" style="font-weight:bold;"></i>
                </a>
            </td>
        </tr>
    </tfoot>
</table>

In addition, I added some jquery code to add new for each click.

My c# code in OnPostAsync():

//After some processing on Bs

foreach (B B in A.Bs)
{
    if (B.Id == 0)
    {
        C C = await _context.C.Where(x =>
                                                        x.Code1 == B.C.Code1 &&
                                                        x.Code2 == B.C.Code2 &&
                                                        x.Code3 == B.C.Code3
                                                        ).SingleOrDefaultAsync();
        B.C = C;
        _context.Attach(B.C).State = EntityState.Unchanged;
    }
    else
    {
        C C = await _context.C.Where(x => x.Id == B.C.Id).SingleOrDefaultAsync();
        B.C = C;
    }
}

_context.Attach(A).State = EntityState.Modified;
await _context.SaveChangesAsync();

Table A is the top parent table which have children of B class, and B class have one child of C. C table already have some data which can be used as a dropdownlist in view to be chosen by the user.

After submit the form (Edit.cshtml), the B class has a C class with the following properties:

Name = null

Code1 = "1"

Code2 = "11"

Code3 = "13"

As you see in the code above, I use C properties to fetch the original C record and replace the instance B.C to the C just loaded (when B is a new record):

B.C = C;

The problem is when submit the form the code works perfectly, but a new record of C table added with Name equal to null. This problem occurred only when B is a new record. Bs with Id > 0 is good.

So what is the problem?

And if the problem is context is keep tracking C, how to stop tracking the changes on it.

Note: I already user AsNoTracking() and _context.attach(B.C).State = EntityState.Unchanged before and the problem is the same.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source