我正在使用 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# 端无法从中获得任何好处?