'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 |
|---|
