删除子实体生成错误查询?

时间:2014-06-11 16:42:37

标签: entity-framework

以下代码

using System;
using System.Linq;
using System.Data.Entity;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using System.Data.SqlClient;
using System.Reflection;

namespace testef {
    public class Order {
        public Int32 Id { get; set; }
        public String O { get; set; }

        public virtual ICollection<OrderDetail> Details { get; set; }
    }

    public class OrderDetail {
        public virtual Order Order { get; set; }
        public Int32 Id { get; set; }
        public String D { get; set; }
        public Boolean IsActive { get; set; }
    }

    public class OrderDetailConfiguration : EntityTypeConfiguration<OrderDetail> {
        public OrderDetailConfiguration()
            : base() {
            HasRequired(d => d.Order).WithMany(o => o.Details);
        }
    }

    public class TestEFContext : DbContext {
        public DbSet<Order> Orders { get; set; }
        public DbSet<OrderDetail> Details { get; set; }

        public TestEFContext(String cs)
            : base(cs) {
            Database.SetInitializer<TestEFContext>(new DropCreateDatabaseAlways<TestEFContext>());
            //Database.SetInitializer<TestEFContext>(null);
            //Database.SetInitializer<TestEFContext>(new CreateDatabaseIfNotExists<TestEFContext>());
            //Database.SetInitializer<TestEFContext>(new CustomDataBaseInitializer());

        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder) {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Configurations.Add(new OrderDetailConfiguration());
        }
    }

    public class CustomDataBaseInitializer : CreateDatabaseIfNotExists<TestEFContext> {
        public CustomDataBaseInitializer() : base() {
        }
    }

    class Program {
        static void Main(string[] args) {
            String cs = @"Data Source=ALIASTVALK;Initial Catalog=TestEF;Integrated Security=True; MultipleActiveResultSets=True";
            using (TestEFContext ctx = new TestEFContext(cs)) {
                Order o = new Order {
                    O = "O1",
                    Details = new List<OrderDetail>{
                        new OrderDetail { D = "D11", IsActive = true},
                        new OrderDetail { D = "D12", IsActive = false}
                    }
                };
                ctx.Orders.Add(o);
                ctx.SaveChanges();
            }


            using (TestEFContext ctx = new TestEFContext(cs)) {
                //OrderDetail d = new OrderDetail { Id = 1};
                //ctx.Details.Attach(d);
                OrderDetail d = ctx.Details.Where(x => x.Id == 1).First();
                ctx.Details.Remove(d);
                ctx.SaveChanges();            
                // ==> exec sp_executesql N'DELETE [dbo].[OrderDetails] WHERE (([Id] = @0) AND ([Order_Id] = @1))',N'@0 int,@1 int',@0=1,@1=1
            }
        }
    }
}

生成以下sql:

exec sp_executesql N'DELETE [dbo].[OrderDetails] WHERE (([Id] = @0) AND ([Order_Id] = @1))',N'@0 int,@1 int',@0=1,@1=1

我无法弄明白为什么AND ([Order_Id] = @1。对我来说,因为PK是Id,所以Id上的WHERE必须足够!

我哪里错了?

1 个答案:

答案 0 :(得分:1)

这是团队制定的设计决策。我不会考虑你的立场或EF队的战术错误......只是选择。两者都有好处。我不会挂断它,部分原因是删除在大多数应用程序中并不常见,部分原因是如果性能问题,可以轻松解决。

如果您只想执行一个查询,请执行以下操作:

ctx.Database.ExecuteSqlCommand("delete from [dbo].[OrderDetails] where Id = @p0", 1);