以下是我的元模型。
根据上图,C的实例必须属于委托人A或B,而不是两者。
我如何正确强制执行该操作? 目前我在C上有以下属性:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EF_CodeFirst_XOR
{
using System.Data.Entity;
public class XorDemo : DbContext
{
public XorDemo()
: base("name=XorDemo")
{
}
public virtual DbSet<Root> Roots { get; set; }
public virtual DbSet<A> As { get; set; }
public virtual DbSet<B> Bs { get; set; }
public virtual DbSet<C> Cs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<C>()
.HasOptional(e => e.A)
.WithOptionalPrincipal(e => e.C);
modelBuilder.Entity<C>()
.HasOptional(e => e.B)
.WithOptionalPrincipal(e => e.C);
}
}
public class Root
{
public int Id { get; set;}
[Required]
public A A { get; set; }
[Required]
public B B { get; set; }
}
public class A
{
[Key, ForeignKey(nameof(Root))]
public int Id { get; set; }
public virtual C C { get; set; }
[Required]
public virtual Root Root { get; set; }
}
public class B
{
[Key, ForeignKey(nameof(Root))]
public int Id { get; set; }
public virtual C C { get; set; }
[Required]
public virtual Root Root { get; set; }
}
public class C
{
public int Id { get; set; }
public virtual A A { get; set; }
public virtual B B { get; set; }
[Required]
[NotMapped]
[Obsolete(message:"Internal. Only for validation!")]
public string Constraint_A_Xor_B
{
get => A != null ^ B != null ? "Valid" : null;
set { }
}
}
}
通过在XOR约束失败时返回null来使[Required]约束无效,从而完成工作。我认为为此目的在课堂上添加一个属性是不合适的。
可以通过其他方式强制执行约束吗?
为了完整起见,以下是整个代码。
class Program
{
static void Main(string[] args)
{
var ctx = new XorDemo();
Root r = new Root();
r.A = new A {Root = r};
C Ca = new C();
r.A.C = Ca;
Ca.A = r.A;
r.B = new B {Root = r};
C Cb = new C {B = r.B};
ctx.Roots.Add(r);
ctx.SaveChanges();
}
}
编辑:驱动程序。
{{1}}
答案 0 :(得分:2)
我实际上并没有在映射中实现它,但我会在数据实体本身中执行它,其中包含以下内容:
public class C
{
public int Id { get; set; }
private virtual A _a;
public virtual A A
{
get
{
return _a;
}
set
{
if (value == null)
throw new ArgumentNullException("A", "You must have A or B.");
if (_b != null)
throw new ConstraintException("You can either have A or B; make up your mind!");
if (value != _a)
_a = value;
}
}
private virtual B _b;
public virtual B B
{
get
{
return _b;
}
set
{
if (value == null)
throw new ArgumentNullException("B", "You must have A or B.");
if (_a != null)
throw new ConstraintException("You can either have A or B; make up your mind!");
if (value != _b)
_b = value;
}
}
public class C(A a)
{
if (a == null)
throw new ArgumentNullException("a");
this._a = a;
}
public class C(B b)
{
if (b == null)
throw new ArgumentNullException("b");
this._b = b;
}
public SwitchBforA(A a)
{
if (a == null)
throw new ArgumentNullException("a", "You'd end up with both A and B null.");
_a = a;
_b = null;
}
public SwitchAforB(B b)
{
if (b == null)
throw new ArgumentNullException("b", "You'd end up with both A and B null.");
_a = null;
_b = b;
}
}
您可能还应该以通常的方式在数据库中添加约束。