嗨我需要知道如果之前不存在行,如何在EF6中插入带有2个外键的父/子行。我在c#MVC 5中使用MSSQL db使用EF6进行数据库通信。 我有4个表与相应的类。
下一步说明:表格包含列和行。 Row有单元格,但由于一个单元属于列,因此列也有单元格。这意味着一个单元格被行和列阻止(使用外键)。 模型类是:
[Table("TD_Tables")]
public class TD_Table
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TD_TableId { get; set; }
public bool Active { get; set; }
public string Orientation { get; set; }
public int TenderDefinitionId { get; set; }
[ForeignKey("TenderDefinitionId")]
public TenderDefinition TenderDefinition { get; set; }
public virtual ICollection<TD_Column> Columns { get; set; }
public virtual ICollection<TD_Row> Rows { get; set; }
}
[Table("TD_Rows")]
public class TD_Row
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TD_RowId { get; set; }
public bool Active { get; set; }
public int Sort { get; set; }
public int TD_TableId { get; set; }
[ForeignKey("TD_TableId")]
public TD_Table Table { get; set; }
public virtual ICollection<TD_Cell> Cells { get; set; }
}
[Table("TD_Columns")]
public class TD_Column
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int? TD_ColumnId { get; set; }
public bool Active { get; set; }
public string ColumnName { get; set; }
public int Sort { get; set; }
public int TD_TableId { get; set; }
[ForeignKey("TD_TableId")]
public TD_Table Table { get; set; }
public int TD_ColumnTypeId { get; set; }
[ForeignKey("TD_ColumnTypeId")]
public TD_ColumnType ColumnType { get; set; }
public virtual ICollection<TD_Cell> Cells { get; set; }
}
[Table("TD_Cells")]
public class TD_Cell
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int TD_CellId { get; set; }
public bool Active { get; set; }
public string CellValue { get; set; }
public int? TD_ColumnId { get; set; }
[ForeignKey("TD_ColumnId")]
public virtual TD_Column Column { get; set; }
public int? TD_RowId { get; set; }
[ForeignKey("TD_RowId")]
public virtual TD_Row Row { get; set; }
}
对于插入DB,我正在创建一个包含所有行,列的表模型对象 首先是单元格,然后在一次调用中插入全部创建表模型对象:
{
var model = new TD_Table();
model.Active = true;
//number of columns to create
for(int i =0; i < columnsNum.AsInt(0); i++)
{
var column = new TD_Column()
{
Active = true,
ColumnName = "",
ColumnTypeId = (int)Core.Enums.TD_ColumnType.Text,
Sort = model.Columns.Count
};
model.Columns.Add(column);
}
//number of rows to create
for (int i = 0; i < rowsNum.AsInt(0); i++)
{
var row = new TD_Row()
{
Active = true,
Sort = i,
TD_TableId = model.TD_TableId
};
for(int c = 0; c < model.Columns.Count; c++)
{
var cell = new TD_Cell()
{
Active = true,
CellValue = "",
TD_ColumnId = model.Columns[c].TD_ColumnId,
Column = model.Columns[c]
};
model.Columns[c].Cells.Add(cell);
row.Cells.Add(cell);
}
model.Rows.Add(row);
}
// add table model in parent definition model
tender.TenderContent.TenderDefinition.Tables.Add(model);
}
在存储库中,我正在更新现有的父定义并添加新表或使用所有子行更新现有的表:
Tender Update(Tender tender)
{
using (var db = new TenderDbContext())
{
var t = db.Tenders.
Include(x => x.TenderContent).
Include(x => x.TenderContent.TenderDefinition).
//Include(x => x.TenderContent.TenderDefinition.Tables).
Include(x => x.TenderContent.TenderDefinition.Tables.Select(y => y.Columns.Select(z => z.Cells))).
Include(x => x.TenderContent.TenderDefinition.Tables.Select(y => y.Rows.Select(z => z.Cells))).
Include(x => x.TenderContent.Survey).
Include(x => x.TenderContent.Survey.Questions).
Where(x => x.TenderId == tender.TenderId).FirstOrDefault();
foreach (var table in tender.TenderContent.TenderDefinition.Tables.Where(x => x.Active))
{
var tableId = table.TD_TableId;
var existingTable = t.TenderContent.TenderDefinition.Tables
.Where(c => c.TD_TableId == tableId)
.FirstOrDefault();
if (existingTable != null)
{
db.Entry(existingTable).CurrentValues.SetValues(table);
if (table.Columns != null && table.Columns.Any())
{
foreach (var column in table.Columns.Where(x => x.Active))
{
var existingColumn = db.TD_Columns.Where(x => x.TD_ColumnId == column.TD_ColumnId).FirstOrDefault();
if (existingColumn != null)
db.Entry(existingColumn).CurrentValues.SetValues(column);
else
existingTable.Columns.Add(column);
}
}
if (table.Rows != null && table.Rows.Any())
{
foreach (var row in table.Rows.Where(x => x.Active))
{
var existingRow = db.TD_Rows.Where(x => x.TD_RowId == row.TD_RowId).FirstOrDefault();
if (existingRow != null)
{
db.Entry(existingRow).CurrentValues.SetValues(row);
foreach (var cell in row.Cells.Where(x => x.Active))
{
var cellExisting = db.TD_Cells.Where(q => q.TD_CellId == cell.TD_CellId).FirstOrDefault();
if (cellExisting != null)
db.Entry(cellExisting).CurrentValues.SetValues(cell);
else
row.Cells.Add(cell);
}
}
else
existingTable.Rows.Add(row);
}
}
}
else
t.TenderContent.TenderDefinition.Tables.Add(table); //insert table with all children
}
db.SaveChanges();
return t;
}
}
我的主要问题是插入新表后例如。 t.TenderContent.TenderDefinition.Tables.Add(table)TD_Cells行重复,RowId值已填充,ColumnId为null且ColumnId值已弹出且RowId为null。因此,如果我想插入10个带有2个外键行和列id的单元格,我只有20个单元格,只有1个键 问题是,当我创建一个单元格时,我在列和行中添加了该单元格,EF不知道如何将该单元格映射为具有2个外键。如果我只添加一个将只有1个密钥填充。任何人都可以找到这里的错误,处理这种情况的最佳方法是什么?