1

我正在使用 EF 4.3.1 并希望创建一个附件对象并单独保存其二进制数据。因此,我在数据库中创建了两个表:Attachments 和 AttachmentData。这是屏幕截图或它们的关系。

这是我的课程:

public class Attachment
{
    public int Id { get; set; }
    public string Name { get; set; }
    public AttachmentData Content { get; set; }
}

[Table("AttachmentData")]
public class AttachmentData
{
    public int Id { get; set; }
    public byte[] Data { get; set; }
}

public class AttachmentConfig : EntityTypeConfiguration<Attachment>
{
    public AttachmentConfig()
    {
        HasRequired(att => att.Content)
            .WithRequiredPrincipal()
            .WillCascadeOnDelete();

        Property(att => entity.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        Property(entity => entity.Name).IsRequired();
    }
}

我们使用存储库模式来访问数据库:

public class Repository
{
    private readonly Context _db = new Context(); 

    public Attachment Add(string fileName, byte [] data)
    {
        var att = new Attachment
                      {
                          Name = fileName,
                          Content = new AttachmentData {Data = data}
                      };

        _db.Documents.Add(att);
        _db.SaveChanges();

        return att;
    }

    public void Delete(int id)
    {
        /* Try to find in local context
         * otherwise exception might appear:
         * "An object with the same key already exists in the ObjectStateManager. 
         * The ObjectStateManager cannot track multiple objects with the same key."
         */
        var att = _db.Documents.Local
            .FirstOrDefault(a => a.Id == id) ?? new Attachment {Id = id};

        _db.Entry(att).State = EntityState.Deleted;            
        _db.SaveChanges();            
    }
}

我写了一个简单的测试,看看我是否可以添加和删除附件:

public void Can_Add_And_Delete()
{
    const string fileName = "FileName.tst";
    var data = new byte[] {0, 1, 2, 3, 4, 5};

    /*************
    * Works fine *
    *************/
    var cont = new Context();
    var att1 = new Attachment
               {
                   Name = fileName,
                   Content = new AttachmentData {Data = data}
               };

    cont.Documents.Add(att1);
    cont.SaveChanges();

    cont.Documents.Remove(att1);
    cont.SaveChanges();

    /********************** 
    * Throws an exception *
    *********************** 
    * The operation failed: The relationship could not be changed because
    * one or more of the foreign-key properties is non-nullable. When a change 
    * is made to a relationship, the related foreign-key property is set to 
    * a null value. If the foreign-key does not support null values, a new 
    * relationship must be defined, the foreign-key property must be assigned
    * another non-null value, or the unrelated object must be deleted. 
    */

    var repo = new Repository();
    var att2 = repo.Add(fileName, data);
    repo.Delete(att2.Id);
}            

从抛出异常的详细描述中可以清楚地看出,问题是由上下文中存在 AttachmentData 实体引起的。但是我认为一旦将 Attachment 状态设置为已删除(因为配置了 1 对 1 关系),上下文将足够智能以删除 AttachmentData。如果不是这样,那么使用 WillCascadeOnDelete() 方法有什么意义呢?是否仅用于正确的数据库关系生成,而 C# 端无法从中获得任何好处?

4

0 回答 0