Ric*_*ard 11 entity-framework entity-framework-5
当我尝试同时添加一个包含多个子节点的实体时,我在使用EF重新排序插件时遇到问题.我有一个3级结构,每个(Outer 1--* Item 1--* SubItem)之间有一对多的关系.如果我尝试插入带有Items和Subitems的新Outer,则包含SubItems的Items最终会被插入.
示例代码(.NET 4.5,EF 5.0.0-rc):
public class Outer
{
public int OuterId { get; set; }
public virtual IList<Item> Items { get; set; }
}
public class Item
{
public int OuterId { get; set; }
[ForeignKey("OuterId")]
public virtual Outer Outer { get; set; }
public int ItemId { get; set; }
public int Number { get; set; }
public virtual IList<SubItem> SubItems { get; set; }
}
public class SubItem
{
public int SubItemId { get; set; }
[ForeignKey("ItemId")]
public virtual Item Item { get; set; }
public int ItemId { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Outer> Outers { get; set; }
public DbSet<Item> Items { get; set; }
public DbSet<SubItem> SubItems { get; set; }
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());
MyContext context = new MyContext();
// Add an Outer object, with 3 Items, the middle one having a subitem
Outer outer1 = new Outer { Items = new List<Item>() };
context.Outers.Add(outer1);
outer1.Items.Add(new Item { Number = 1, SubItems = new List<SubItem>() });
outer1.Items.Add(new Item { Number = 2, SubItems = new List<SubItem>(new SubItem[] { new SubItem() }) });
outer1.Items.Add(new Item { Number = 3, SubItems = new List<SubItem>() });
context.SaveChanges();
// Print the order these have ended up in
foreach (Item item in context.Items)
{
Console.WriteLine("{0}\t{1}", item.ItemId, item.Number);
}
// Produces output:
// 1 2
// 2 1
// 3 3
}
}
Run Code Online (Sandbox Code Playgroud)
我知道Alex James的这个答案,其中指出插入可能需要重新排序以满足关系约束,但这不是问题.他的回答还提到他们无法跟踪保存订单的结构中的项目顺序,例如列表.
我想知道的是我如何才能订购这些刀片.虽然我可以依靠通过除PK以外的字段对插入的项目进行排序,但如果我可以依赖PK顺序,它会更有效率.我真的不想使用多个SaveChanges调用来完成此任务.
我正在使用EF5 RC,但从其他未解决的问题来看,这已经有一段时间了!
我想知道的是我如何才能订购这些刀片.
你不能.数据库命令的顺序是EF的内部行为.如果要控制命令的顺序,请不要使用从低级数据库交互中抽象出来的工具 - 直接使用SQL.
根据评论进行编辑:
是的,这是低级别的交互,因为在使用您无法控制的抽象时,您会对SQL命令的顺序产生期望.在高层次上,你会得到不同的东西,因为你正在使用那些不能用于抽象的期望.如果要控制SQL命令的顺序,则必须通过逐个保存项目(=>多个SaveChanges和TransactionScope)来强制执行EF,或者自己编写SQL.否则使用单独的列进行排序.
顺便说一句.EF不会像您看到的那样保存实体.它有自己的更改跟踪器,包含对所有附加实例的引用.引用保存在多个Dictionary实例中,字典不保留插入顺序.如果这些集合用于生成SQL命令(我猜它们是),则无法保证订单.
数据库中的表是集合。这意味着订单无法保证。我假设在您的示例中您希望结果按“数字”排序。如果这就是您想要的,如果该数字发生变化并且它不再反映数据库中的顺序,您将怎么做?
如果您确实希望按特定顺序插入行,那么多个 SaveChanges 是您的最佳选择。
没有人愿意多次调用 SaveChanges 的原因是因为这感觉就是这样:一个肮脏的黑客。
由于主键是一个技术概念,因此无论如何在该键上对结果进行排序都不应该具有任何功能意义。您可以按特定字段对结果进行排序,并为此使用数据库索引。您可能不会看到速度上的差异。
明确顺序还有其他好处:对于必须维护它的人来说更容易理解。否则,该人必须知道主键排序很重要并给出正确的结果,因为在应用程序的其他(完全)不相关的部分中,它意外地与数字字段的顺序相同。
| 归档时间: |
|
| 查看次数: |
6540 次 |
| 最近记录: |