Entity Framework 核心(代码优先)不会插入到相关表中
Entity Framework Core (Code First) won't insert into dependent tables
我有一个使用 Entity Framework Core 3.1.5 的应用程序 (.NET Framework 4.8)。
(我不敢升级,因为我觉得这可能会破坏其他依赖项 - 我很高兴它能按原样工作。)
我正在使用“代码优先”方法将数据从 SharePoint 导出到 SQL tables。
某些 SharePoint“列表”(tables 的 SharePoint 概念)可以包含 M:N 映射,我必须将其分成单独的 SQL tables。
一些代码:
// Base class for all parent tables
internal abstract class SharePointListModel
{
[SharePointColumn("ID")]
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public virtual void PostProcess()
{
}
}
// Base class for all child tables
internal abstract class AdditionalTableModel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
}
// This is the child table, which is never inserted
[Table("MyMappingTable", Schema = "myschema")]
internal class MyMappingTable : AdditionalTableModel
{
// This points to a third table, but it could really
// be any value. It could also be a string or BLOB etc.
public int OtherTableId { get; set; }
}
// This is the parent table, which is inserted correctly
[Table("MySharePointTable", Schema = "myschema")]
internal class MySharePointTable : SharePointListModel
{
[SharePointColumn("SharePointLookupColumn", UseId = true)]
[NotMapped]
public int[] OtherTableIds { get; set; }
public List<MyMappingTable> Mappings { get; set; } // Making the property virtual doesn't change anything either
public override void PostProcess()
{
Mappings = OtherTableIds?.Select(x => new MyMappingTable { OtherTableId = x }).ToList();
}
}
Entity Framework 似乎理解这一点,因为 dbContext.CreateTable() 创建了一个包含三列的 table “MyMappingTable”(尽管只定义了两个属性):Id、OtherTableId (实际上是外键,但 EF 不知道)和 MySharePointTableId(外键).
但是当我像这样插入数据时,M:N 映射 table (MyMappingTable) 仍然是空的:
IList<MySharePointTable> = LoadSharePointTable();
dbContext.AddRange(data);
dbContext.SaveChanges();
显式映射 parent 也无济于事:
[Table("MyMappingTable", Schema = "myschema")]
internal class MyMappingTable : AdditionalTableModel
{
public virtual MySharePointTable Parent { get; set; }
public int OtherTableId { get; set; }
}
// [...]
public override void PostProcess()
{
Mappings = OtherTableIds?.Select(x => new MyMappingTable { Parent = this, OtherTableId = x }).ToList();
}
我也试过显式插入依赖行,但这并没有改变任何东西:
IList<MySharePointTable> = LoadSharePointTable();
dbContext.AddRange(data);
IEnumerable<MyMappingTable> dependentRows = data.SelectMany(x => x.Mappings ?? Enumerable.Empty<MyMappingTable>());
dbContext.AddRange(dependentRows);
dbContext.SaveChanges();
或者像这样,但这也没有改变任何东西,child table 仍然是空的:
IList<MySharePointTable> = LoadSharePointTable();
dbContext.AddRange(data);
IEnumerable<MyMappingTable> dependentRows = data.SelectMany(x => x.Mappings ?? Enumerable.Empty<MyMappingTable>());
dbContext.Set<MyMappingTable>().AddRange(dependentRows);
dbContext.SaveChanges();
此处的插入代码略有简化,因为我实际上是将反射用于通用方法,但我认为这无关紧要。
我做错了什么?
确定一下,这两个名字不应该匹配吗?因为一切似乎都是正确的,所以您不需要为子实体 EF 处理它而显式插入。
呃。好像我一直在看错误的数据库...
我有一个使用 Entity Framework Core 3.1.5 的应用程序 (.NET Framework 4.8)。 (我不敢升级,因为我觉得这可能会破坏其他依赖项 - 我很高兴它能按原样工作。)
我正在使用“代码优先”方法将数据从 SharePoint 导出到 SQL tables。 某些 SharePoint“列表”(tables 的 SharePoint 概念)可以包含 M:N 映射,我必须将其分成单独的 SQL tables。
一些代码:
// Base class for all parent tables
internal abstract class SharePointListModel
{
[SharePointColumn("ID")]
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public virtual void PostProcess()
{
}
}
// Base class for all child tables
internal abstract class AdditionalTableModel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
}
// This is the child table, which is never inserted
[Table("MyMappingTable", Schema = "myschema")]
internal class MyMappingTable : AdditionalTableModel
{
// This points to a third table, but it could really
// be any value. It could also be a string or BLOB etc.
public int OtherTableId { get; set; }
}
// This is the parent table, which is inserted correctly
[Table("MySharePointTable", Schema = "myschema")]
internal class MySharePointTable : SharePointListModel
{
[SharePointColumn("SharePointLookupColumn", UseId = true)]
[NotMapped]
public int[] OtherTableIds { get; set; }
public List<MyMappingTable> Mappings { get; set; } // Making the property virtual doesn't change anything either
public override void PostProcess()
{
Mappings = OtherTableIds?.Select(x => new MyMappingTable { OtherTableId = x }).ToList();
}
}
Entity Framework 似乎理解这一点,因为 dbContext.CreateTable() 创建了一个包含三列的 table “MyMappingTable”(尽管只定义了两个属性):Id、OtherTableId (实际上是外键,但 EF 不知道)和 MySharePointTableId(外键).
但是当我像这样插入数据时,M:N 映射 table (MyMappingTable) 仍然是空的:
IList<MySharePointTable> = LoadSharePointTable();
dbContext.AddRange(data);
dbContext.SaveChanges();
显式映射 parent 也无济于事:
[Table("MyMappingTable", Schema = "myschema")]
internal class MyMappingTable : AdditionalTableModel
{
public virtual MySharePointTable Parent { get; set; }
public int OtherTableId { get; set; }
}
// [...]
public override void PostProcess()
{
Mappings = OtherTableIds?.Select(x => new MyMappingTable { Parent = this, OtherTableId = x }).ToList();
}
我也试过显式插入依赖行,但这并没有改变任何东西:
IList<MySharePointTable> = LoadSharePointTable();
dbContext.AddRange(data);
IEnumerable<MyMappingTable> dependentRows = data.SelectMany(x => x.Mappings ?? Enumerable.Empty<MyMappingTable>());
dbContext.AddRange(dependentRows);
dbContext.SaveChanges();
或者像这样,但这也没有改变任何东西,child table 仍然是空的:
IList<MySharePointTable> = LoadSharePointTable();
dbContext.AddRange(data);
IEnumerable<MyMappingTable> dependentRows = data.SelectMany(x => x.Mappings ?? Enumerable.Empty<MyMappingTable>());
dbContext.Set<MyMappingTable>().AddRange(dependentRows);
dbContext.SaveChanges();
此处的插入代码略有简化,因为我实际上是将反射用于通用方法,但我认为这无关紧要。
我做错了什么?
确定一下,这两个名字不应该匹配吗?因为一切似乎都是正确的,所以您不需要为子实体 EF 处理它而显式插入。
呃。好像我一直在看错误的数据库...