C# 删除在多个实体上拆分的表行时出错
我想删除在两个实体上拆分的表行 如果我试图删除主实体,则在我未使用C# 删除在多个实体上拆分的表行时出错,c#,entity-framework,C#,Entity Framework,我想删除在两个实体上拆分的表行 如果我试图删除主实体,则在我未使用上下文.Entry(…).Reference加载相关的其他实体之前,会出现一个错误 当我要删除整行时,在之前检索相关实体有点傻吗 如果我对context.Entry(…)行进行注释,则会出现以下错误 遇到无效数据。缺少必需的关系。检查 状态项以确定约束冲突的来源 我在下面添加代码。请有人帮我删除拆分的实体,而不必在之前“加载”相关实体,好吗 using System.Data.Entity; using System.Linq
上下文.Entry(…).Reference加载相关的其他实体之前,会出现一个错误
当我要删除整行时,在之前检索相关实体有点傻吗
如果我对context.Entry(…)
行进行注释,则会出现以下错误
遇到无效数据。缺少必需的关系。检查
状态项以确定约束冲突的来源
我在下面添加代码。请有人帮我删除拆分的实体,而不必在之前“加载”相关实体,好吗
using System.Data.Entity;
using System.Linq;
namespace Split
{
class Program
{
static void Main(string[] args)
{
using (var context = new DataContext())
{
var product = new Product()
{
Name = "my Article",
Photo = new ProductPhoto() { PhotoUrl = "http://myfoto.jpg" }
};
context.Products.Add(product);
context.SaveChanges();
}
using (var context = new DataContext())
{
var product = context.Products.First();
//context.Entry(product).Reference(e => e.Photo).Load();
context.Products.Remove(product);
context.SaveChanges();
}
}
}
class Product
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ProductPhoto Photo { get; set; }
}
class ProductPhoto
{
public virtual int ProductId { get; set; }
public virtual string PhotoUrl { get; set; }
public virtual Product Product { get; set; }
}
class DataContext : DbContext
{
public DataContext()
: base("name=DefaultConnection")
{
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
}
public DbSet<Product> Products { get; set; }
public DbSet<ProductPhoto> ProductPhotos { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>()
.ToTable("Products")
.HasKey(e => e.Id)
.HasRequired(e => e.Photo)
.WithRequiredPrincipal(e => e.Product);
modelBuilder.Entity<ProductPhoto>()
.ToTable("Products")
.HasKey(e => e.ProductId);
base.OnModelCreating(modelBuilder);
}
}
}
使用System.Data.Entity;
使用System.Linq;
名称空间拆分
{
班级计划
{
静态void Main(字符串[]参数)
{
使用(var context=new DataContext())
{
var product=新产品()
{
Name=“我的文章”,
照片=新产品照片(){PhotoUrl=”http://myfoto.jpg" }
};
context.Products.Add(产品);
SaveChanges();
}
使用(var context=new DataContext())
{
var product=context.Products.First();
//context.Entry(product.Reference(e=>e.Photo.Load();
context.Products.Remove(产品);
SaveChanges();
}
}
}
类产品
{
公共虚拟整数Id{get;set;}
公共虚拟字符串名称{get;set;}
公共虚拟产品照片{get;set;}
}
班级产品照片
{
公共虚拟int ProductId{get;set;}
公共虚拟字符串PhotoUrl{get;set;}
公共虚拟产品产品{get;set;}
}
类DataContext:DbContext
{
公共数据上下文()
:base(“name=DefaultConnection”)
{
Configuration.ProxyCreationEnabled=false;
Configuration.LazyLoadingEnabled=false;
}
公共数据库集产品{get;set;}
公共DbSet ProductPhotos{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.ToTable(“产品”)
.HasKey(e=>e.Id)
.has必需(e=>e.Photo)
.具有所需的委托人(e=>e.Product);
modelBuilder.Entity()
.ToTable(“产品”)
.HasKey(e=>e.ProductId);
基于模型创建(modelBuilder);
}
}
}
可能像这样装载产品:
var product = context.Products.Include(x => x.Photo).First();
保存一行,但仍将从数据库加载照片。尝试将级联删除规则添加到模型中。数据库中必须有相应的删除规则,以避免将依赖项加载到内存中最好的方法是使用存根实体:仅具有Id值的实体对象:
var product = context.Products.First();
var photo = new ProductPhoto { ProductId = product.ProductId }; // Stub
context.Entry(photo).State = System.Data.Entity.EntityState.Deleted;
context.Products.Remove(product);
context.SaveChanges();
如果您知道产品
的Id,您甚至可以通过只创建两个存根来删除产品
及其产品照片
。嗨,格特·阿诺德建议的解决方法是在内存中
存根一个用于实体,另一个用于相关子实体
我粘贴了一个新的代码,该代码可以正常工作(参见注释)
我用Gert Arnold提出的想法发布了解决方案,也许代码可以优化,我试着让它尽可能通用
如果您的实体包含任何并发令牌,那么这些属性也是
用于构造DELETE语句。您仍然可以使用存根实体
方法,但需要为并发令牌设置值
属性也是如此
引自:“编程实体框架:DbContext”
作者:朱莉娅·勒曼和罗恩·米勒(O'Reilly)。版权所有2012朱莉娅·勒曼和
罗文·米勒,978-1-449-31296-1。“
using System;
using System.Data.Entity;
using System.Linq;
using System.Reflection;
namespace Split
{
class Program
{
static void Main()
{
Database.SetInitializer(new DropCreateDatabaseAlways<DataContext>());
const int id = 1;
const string split = "Info"; // contract: if the entity being delete has an Info property then the row has been splitted
using (var context = new DataContext()) // Add
{
var product = new Product
{
Name = "my Article 1",
Info = new ProductInfo { PhotoUrl = "http://myphoto.jpg" } // when adding an entity the subEntity MUST BE included on the graph
};
context.Products.Add(product);
context.SaveChanges();
}
using (var context = new DataContext())
{
var product = context.Products.Find(id);
context.Entry(product).Reference(e => e.Info).Load(); // when adding an entity the subEntity COULD BE OR NOT included on the graph, no need to include it if we are not going to modify it
product.Name = "MY ARTICULE 1";
product.Info.PhotoUrl = "HTTP://MYPHOTO.JPG";
context.Entry(product).State = EntityState.Modified;
context.SaveChanges();
}
using (var context = new DataContext())
{
PropertyInfo propertyInfo;
context.Products.Find(id); // uncoment bring it to memory and test with entity in memory
var entity = context.Products.Local.FirstOrDefault(e => e.Id == id);
context.Entry(entity).Reference(e => e.Info).Load();
if (entity != null) // there is a entity already yet in memory
{
propertyInfo = entity.GetType().GetProperty(split); // contract
if (propertyInfo != null)
{
var subEntity = propertyInfo.GetValue(entity); // get subEntity from entity Info property
context.Entry(subEntity).State = EntityState.Detached; // remove sub entity from ChangeTracker API
propertyInfo.SetValue(entity, null); // remove subEntity and relationship
}
context.Entry(entity).State = EntityState.Detached; // remove entity from ChangeTracker API
}
entity = new Product { Id = id }; // new entity stub
propertyInfo = entity.GetType().GetProperty(split); // contract:
if (propertyInfo != null)
{
propertyInfo.SetValue(entity, null); // remove subEntity and and relationship
var subEntity = Activator.CreateInstance(propertyInfo.PropertyType); // create a new subEntity stub
subEntity.GetType().GetProperty("Id").SetValue(subEntity, id); // set the foreinkey relation
context.Entry(subEntity).State = EntityState.Deleted; // mark as deleted on context
}
context.Entry(entity).State = EntityState.Deleted; // delete the entity
context.SaveChanges();
}
}
}
class Product
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ProductInfo Info { get; set; }
}
class ProductInfo
{
public virtual int Id { get; set; }
public virtual string PhotoUrl { get; set; }
public virtual Product Product { get; set; }
}
class DataContext : DbContext
{
public DataContext()
: base("name=DefaultConnection")
{
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
}
public DbSet<Product> Products { get; set; }
public DbSet<ProductInfo> ProductInfos { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>() // one-to-one
.ToTable("Products")
.HasKey(e => e.Id)
.HasRequired(e => e.Info)
.WithRequiredDependent(e => e.Product);
modelBuilder.Entity<ProductInfo>() // map to the same table Products
.ToTable("Products")
.HasKey(e => e.Id);
base.OnModelCreating(modelBuilder);
}
}
}
使用系统;
使用System.Data.Entity;
使用System.Linq;
运用系统反思;
名称空间拆分
{
班级计划
{
静态void Main()
{
SetInitializer(新的DropCreateDatabaseAlways());
const int id=1;
const string split=“Info”//约定:如果要删除的实体具有Info属性,则该行已被拆分
使用(var context=new DataContext())//添加
{
var产品=新产品
{
Name=“我的文章1”,
信息=新产品信息{PhotoUrl=”http://myphoto.jpg“}//添加实体时,子实体必须包含在图形中
};
context.Products.Add(产品);
SaveChanges();
}
使用(var context=new DataContext())
{
var product=context.Products.Find(id);
context.Entry(product).Reference(e=>e.Info).Load();//添加实体时,子实体可以包含在图形中,也可以不包含在图形中,如果我们不打算修改它,则无需包含它
product.Name=“我的文章1”;
product.Info.PhotoUrl=“HTTP://MYPHOTO.JPG”;
context.Entry(product.State=EntityState.Modified;
SaveChanges();
}
使用(var context=new DataContext())
{
PropertyInfo PropertyInfo;
context.Products.Find(id);//取消注释将其带到内存并使用内存中的实体进行测试
var entity=context.Products.Local.FirstOrDefault(e=>e.Id==Id);
context.Entry(entity.Reference(e=>e.Info).Load();
if(entity!=null)//内存中已有一个实体
{
propertyInfo=entity.GetType().GetProperty(拆分);//合同
if(propertyInfo!=null)
{
var subEntity=propertyInfo.GetValue(实体);
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>() // one-to-one
.ToTable("Products")
.HasKey(e => e.Id)
.HasRequired(e => e.Info)
.WithRequiredDependent(e => e.Product);
modelBuilder.Entity<ProductInfo>() // map to the same table Products
.ToTable("Products")
.HasKey(e => e.Id);
//add this code
modelBuilder.Entity<Product>()
.HasRequired(p => p.Photo) // "Photo" defined in Product class for ProductPhoto class's object name
.WithRequiredPrincipal(c => c.Product);// "Product" defined in ProductPhoto class for Product's class object name
base.OnModelCreating(modelBuilder);
}
DbContext.Database.ExecuteSqlCommand($"DELETE FROM Products WHERE Id = {id}");