自定义实体框架多对多导航属性 [英] Custom Entity Framework many-to-many navigation property

查看:130
本文介绍了自定义实体框架多对多导航属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个多对多的映射/数据透视表,我不得不公开为实体,以建立类似于以下的关系(根据这个问题模型实体框架许多加共享关系):





现在,我会喜欢模拟库存实体框架多对多关系的导航属性中存在的EF集合枚举/添加/删除功能。我如何做到这一点?



我希望能够在不影响数据性能的前提下继续查询。显然只是实现以下内容来桥接数据透视表并不能达到这个目标,也不遵循用于管理集合的EF约定:

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

public void AddAnthology(Anthology选集)
{
CompositionAnthologies.Add(new CompositionAnthology(){
Anthology = ,
Composer = Composer
});你可以指出一个例子,或者建议一个起始点点? (注意,我目前使用的是模型,但是将首先转换为代码优先解决方案,因为模特儿似乎很快成为二等公民。)





多对多关系有一个交界处表(CompositionAnthologies)包括一个绑定的ComposerId列,必要的手动创建的FK关系来强制使用Composition.Composer ==所有Anthology.Compositions(和Composition.Anthologies)的Anthology.Composer。以下是连接表所持的关系:





ie必须没有与Anthologies有关的作品,但有不同的作曲者。

解决方案

这是我目前的解决方案。仍然可以接受建议,因为这掩盖了IQueryable,它具有性能上的影响。它也没有上下文,所以不能删除连接(注意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(必须设置父或者小组合成员来形成这个关联);
item.Composer = _parent.Composer;
}
else if(_parent.Composer == null){
_parent.Composer = item.Composer;
}
else if(item.Composer!= _parent.Composer){
throw new InvalidOperationException(Parent and child must not have a different Composer assigned);
}
junction.Add(new CompositionAnthology(){
Anthology = item,
Composer = item.Composer
});
}

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

public bool包含(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();
}

私人ICollection< CompositionAnthology>交点{
get {
return _parent.CompositionAnthologies;
}
}
}


I have a many-to-many mapping/pivot table I had to expose as an Entity in order to model a relationship similar to the following (as per this question Model Entity Framework many-many plus shared relation):

Now, I would like to emulate the EF collection Enumerate/Add/Remove functionality that is present on the navigation property of a 'stock' Entity Framework many-to-many relationship. How would I do that?

I'm hoping for something that I can still query without blowing my data performance. Obviously just implementing the following to bridge the pivot table doesn't accomplish this goal, and also doesn't follow the EF conventions for managing the collection:

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
        });
    }
}

Can you point me at an example or recommend a starting point? (Note I'm using model-first currently, but would switch to code-first for a solution, since model-first seems to be fast becoming a second-class citizen.)


EDIT: Here's further info on the relationship and constraints.

The many-to-many relationship has a junction table ("CompositionAnthologies") including a binding ComposerId column, with necessary manually-created FK relations to enforce Composition.Composer == Anthology.Composer for all Anthology.Compositions (and Composition.Anthologies). Here is the relation as held by the junction table:

i.e.There must be no Compositions related to Anthologies, but having differing Composers.

解决方案

Here's my current solution. Still open to suggestions, as this obscures IQueryable, which has performance ramifications. It also doesn't have Context, so cannot delete junctions (notice the NotImplemented exceptions). The latter issue is not terribly important for me, because my data has a deleted flag that I use anyway.

Here's one side of the relation. They are symmetric.

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;
        }
    }
}

这篇关于自定义实体框架多对多导航属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆