Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/298.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架:更新或删除'时如何删除相关实体;通用';父母亲_C#_Entity Framework_Entity Framework 6_Cascading Deletes - Fatal编程技术网

C# 实体框架:更新或删除'时如何删除相关实体;通用';父母亲

C# 实体框架:更新或删除'时如何删除相关实体;通用';父母亲,c#,entity-framework,entity-framework-6,cascading-deletes,C#,Entity Framework,Entity Framework 6,Cascading Deletes,我有一个产品类,它包含一个图片属性。其他类也可能有图片,例如客户可以有图片 Product.cs: public class Product { public Picture Picture { get; set; } } Customer.cs: public class Customer { public Picture Picture { get; set; } } Picture.cs: public class Picture { public stri

我有一个
产品
类,它包含一个
图片
属性。其他类也可能有图片,例如
客户
可以有
图片

Product.cs:

public class Product
{
    public Picture Picture { get; set; }
} 
Customer.cs:

public class Customer
{
    public Picture Picture { get; set; }
} 
Picture.cs:

public class Picture
{
    public string Type { get; set; }

    public byte[] Content { get; et; }
}
图片始终是可选的,即产品和客户可能有图片,也可能没有图片。但是,图片仅与一个“父”实体(产品或客户)链接。没有父对象,图片就没有存在的意义。请注意,Picture与父类之间没有链接,因为父类可以是多种类型(产品或客户)

另一个要求是,我希望通过快速加载或延迟加载完全控制图片是否加载。例如,在检索产品列表时,我不希望获取图片,但如果请求单个产品,则应包括图片

我的问题:如何配置实体框架以便:

  • 当父记录(产品或客户)被删除时,图片记录被删除
  • 每当父记录更新且新版本不包含图片时,图片记录将被删除
  • 每当父级更新为新图片时,图片记录将被替换(删除+创建记录)
  • 图片是可选的
  • 始终控制图片是否加载
我正在使用fluent-API来定义关系。目前,没有任何级联删除

public class ProductMap : EntityTypeConfiguration<Product>
{
    public ProductMap()
    {
        ToTable("PRODUCTS");

        HasKey(x => x.Id);

        HasOptional(x => x.Picture).WithOptionalDependent().Map(m => m.MapKey("PICTUREID"));
    }
}
公共类ProductMap:EntityTypeConfiguration
{
公共产品地图()
{
ToTable(“产品”);
HasKey(x=>x.Id);
has可选(x=>x.Picture).WithOptionalDependent().Map(m=>m.MapKey(“PICTUREID”);
}
}

我尝试使用WithRequired,但这会产生错误,因为从
图片
产品/客户
没有链接或外键,我在StackOverflow上也发现了这一点,也许它会帮助您:

modelBuilder.Entity<Product>()
    .HasKey(c => c.Id)
    .HasRequired(c => c.User)
    .WithRequiredDependent(c => c.UserProfile)
    .WillCascadeOnDelete(true);
modelBuilder.Entity()
.HasKey(c=>c.Id)
.HasRequired(c=>c.User)
.WithRequiredDependent(c=>c.UserProfile)
.WillCascadeOnDelete(真);
我认为你需要改变你的代码一点,但它应该工作

原职:


也许这对您也有帮助:

我认为您可以将
图片
配置为
ComplexType
,从而在父表中创建
图片
类列的属性

这意味着:

  • 无论何时删除父对象,都会删除相应的
    图片
  • 每当使用新的
    图片
    数据(更新的图片数据或无数据)更新父表时,父表中的相应列也会更新
此处介绍了如何将
图片
实体配置为
ComplexType

至少这是您需要做的:

public class MyDbContext:DbContext
{
    public DbSet<Customer> Customers { get; set; }
    public DbSet<Product> Products { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.ComplexType<Picture>();
    }
}
此外,您还可以为
ComplexType
编写流畅的配置,如下所示:

public class PictureConfig : ComplexTypeConfiguration<Picture>
{
    public PictureConfig()
    {
        Property(t => t.Type).HasColumnName("PictureType");
        Property(t => t.Content).HasColumnName("PictureContent");
    }
}
如果现在添加迁移,它可能如下所示:

    public override void Up()
    {
        CreateTable(
            "dbo.Customers",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    Picture_Type = c.String(),
                    Picture_Content = c.Binary(),
                })
            .PrimaryKey(t => t.Id);

        CreateTable(
            "dbo.Products",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    Picture_Type = c.String(),
                    Picture_Content = c.Binary(),
                })
            .PrimaryKey(t => t.Id);

    }
    public override void Up()
    {
        CreateTable(
            "dbo.Customers",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    PictureType = c.String(),
                    PictureContent = c.Binary(),
                })
            .PrimaryKey(t => t.Id);

        CreateTable(
            "dbo.Products",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    PictureType = c.String(),
                    PictureContent = c.Binary(),
                })
            .PrimaryKey(t => t.Id);

    }
Product---1-----1---Picture ---1------1---Customer
|- Id               |- Id                 |- Id
|- PictureId?                             |- PictureId?
希望这有帮助

根据评论更新: 更新的这一部分并没有给你真正想要的东西,只是提供了一个简单的建议

我认为你正在寻找一种如下的关系:

    public override void Up()
    {
        CreateTable(
            "dbo.Customers",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    Picture_Type = c.String(),
                    Picture_Content = c.Binary(),
                })
            .PrimaryKey(t => t.Id);

        CreateTable(
            "dbo.Products",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    Picture_Type = c.String(),
                    Picture_Content = c.Binary(),
                })
            .PrimaryKey(t => t.Id);

    }
    public override void Up()
    {
        CreateTable(
            "dbo.Customers",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    PictureType = c.String(),
                    PictureContent = c.Binary(),
                })
            .PrimaryKey(t => t.Id);

        CreateTable(
            "dbo.Products",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    PictureType = c.String(),
                    PictureContent = c.Binary(),
                })
            .PrimaryKey(t => t.Id);

    }
Product---1-----1---Picture ---1------1---Customer
|- Id               |- Id                 |- Id
|- PictureId?                             |- PictureId?
也就是说,您可以在父类上保持
nullable
PictureId
,并在图片更改时更改此
PictureId

缺点:您需要自己管理数据操作活动(CRUD)


优点:这样您可以完全控制何时加载图像,因为加载父对象不会自动加载
图片。此外,这还使您能够将图片与数据库解耦,并使用某种blob存储(可能在云端或其他位置)。

添加调用以删除要删除产品的图片。如果您在许多地方这样做,请重新考虑封装此操作。我发现EF配置不够透明,但是在DeleteProduct方法或DeleteCustomer方法中简单地调用delete很容易阅读和理解

您可以执行以下操作:

public abstract class Picture
{
    public int Id {get;set;}
    public string Type { get; set; }
    public byte[] Content { get; set; }
}

public class ProductImage:Picture
{
    public int ProductId {get;set;}
    public virtual Product Product {get;set;}
}
public class CustomerImage:Picture
{
   public int CustomerId {get;set;}
   public virtual Customer Customer{get;set;}
}
然后您可以这样配置: 例如,对于产品:

HasOptional(x=>x.ProductImage)
 .withRequired(x=>x.Product)
 .HasForeignKey(x=>x.ProductId); //cascade on delete is default true
通过这种方式,您可以在需要时加载图片,如果删除产品项,图像也将被删除。 图像是可选的,可以替换。 更新时,必须指定新图像或删除旧图像


希望这个选择能帮助你准确地选择你想要的

这要求依赖类有一个引用父类的属性(UserProfile有一个名为User的属性),在我的情况下不是这样。这种关系需要是单向的。为什么还要创建一个单独的表,里面有图片,而产品/用户表本身没有图片信息?你从中受益了吗?或者你在任何地方都需要它吗?因为图片是一个很大的数据块,我想控制何时获取它,何时不获取它。因为我不能告诉实体框架忽略一列,但我可以告诉实体框架忽略一个关系,这就是我设计它的方式。嗯,但你可以告诉EF忽略一列,只要不选择它。你可以通过将
LazyLoading
设置为false,告诉EF不加载关系!谢谢你的回答,我觉得很有趣。然而,我遇到了两个问题。一是复杂类型不能为null。由于图片始终是可选的,这是一个问题。第二,我想完全控制何时加载图片,何时不加载,因为它是一个大文件。这个级别