自定义实体框架多对多导航属性

时间:2013-05-01 05:03:08

标签: .net sql-server entity-framework entity-framework-5

我有一个多对多的映射/数据透视表我不得不作为实体公开,以便建模类似于以下的关系(根据此问题Model Entity Framework many-many plus shared relation):

enter image description here

现在,我想模拟“库存”实体框架多对多关系的导航属性中存在的EF集合枚举/添加/删除功能。我该怎么做?

我希望能在不破坏数据性能的情况下继续查询。显然,只是实现以下来桥接数据透视表并不能实现这一目标,也不遵循EF约定来管理集合:

public partial class Composition {
    public IEnumerable<Anthology> Anthologies {
        get {
            return CompositionAnthologies.Select(e => e.Anthology);
        }
    }

    public void AddAnthology(Anthology anthology)
    {
        CompositionAnthologies.Add(new CompositionAnthology() {
            Anthology = anthology,
            Composer = Composer
        });
    }
}

你能指出一个例子或推荐一个起点吗? (注意我目前正在使用模型优先,但是会转向代码优先解决方案,因为模型优先似乎很快成为二等公民。)


编辑:这是关于关系和约束的进一步信息。

多对多关系有一个联结表(“CompositionAnthologies”),包括一个绑定的ComposerId列,必要的手动创建的FK关系,以强制所有Anthology.Compositions(和Composition)的Composition.Composer == Anthology.Composer .Anthologies)。以下是联结表所保持的关系:

enter image description here

即必须没有与选集有关的作品,但有不同的作曲家。

1 个答案:

答案 0 :(得分:0)

这是我目前的解决方案。仍然愿意接受建议,因为这会掩盖IQueryable,它具有性能影响。它也没有Context,因此无法删除联结(请注意NotImplemented异常)。后一个问题对我来说并不是非常重要,因为我的数据有一个删除的标志,无论如何我都会使用。

这是关系的一面。它们是对称的。

public partial class Composition {
    public ICollection<Anthology> Anthologies {
        get {
            return new JunctionedAnthologies(this);
        }
    }
}

public class JunctionedAnthologies : ICollection<Anthology> {
    private readonly Composition _parent;

    public JunctionedAnthologies(Composition parent)
    {
        _parent = parent;
    }

    public void Add(Anthology item) {
        if (item.Composer == null) {
            if (_parent.Composer == null) throw new InvalidOperationException("The parent or child Composer must be set to form this association");
            item.Composer = _parent.Composer;
        }
        else if (_parent.Composer == null) {
            _parent.Composer = item.Composer;
        }
        else if (item.Composer != _parent.Composer) {
            throw new InvalidOperationException("The parent and child must not have a differing Composer assigned");
        }
        junction.Add(new CompositionAnthology() {
            Anthology = item,
            Composer = item.Composer
        });
    }

    public void Clear() {
        throw new NotImplementedException();
    }

    public bool Contains(Anthology item) {
        return junction.Any(j => j.Anthology == item);
    }

    public void CopyTo(Anthology[] array, int arrayIndex) {
        throw new NotImplementedException();
    }

    public int Count {
        get { return junction.Count; }
    }

    public bool IsReadOnly {
        get { return false; }
    }

    public bool Remove(Anthology item) {
        throw new NotImplementedException();
    }

    public IEnumerator<Anthology> GetEnumerator() {
        return junction.Select(e => e.Anthology).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator() {
        return GetEnumerator();
    }

    private ICollection<CompositionAnthology> junction {
        get {
            return _parent.CompositionAnthologies;
        }
    }
}