我正在使用EF 4.3.1,并希望创建一个附件对象并分别保留其二进制数据。所以,我在数据库中创建了两个表:Attachments和AttachmentData。这是screenshot或他们的关系。
以下是我的课程:
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#端无法获得它的任何好处?