Linq to sql Linq到SQL:多对多支持类

Linq to sql Linq到SQL:多对多支持类,linq-to-sql,generics,many-to-many,generic-list,Linq To Sql,Generics,Many To Many,Generic List,我想要一个支持课程来帮助处理多对多关系 正如我现在看到的,它可以是一个双泛型类,您可以在围绕关系的一个或两个实体分部类中定义 让它允许访问另一个表而不必特别提到关系表应该很容易。然而,从集合中添加或删除有点棘手。您还需要在关系表中添加一行,并根据所做的操作提交或删除该行 这可以通过传递给这个泛型类的函数来完成吗 这样的类是否存在?如果不存在,它是否可以实现?很难(甚至不可能)在LINQ to SQL中创建一个感觉像本机的解决方案,因为这样的解决方案必须以以下方式工作: 多集合应建模为其他多实体上

我想要一个支持课程来帮助处理多对多关系

正如我现在看到的,它可以是一个双泛型类,您可以在围绕关系的一个或两个实体分部类中定义

让它允许访问另一个表而不必特别提到关系表应该很容易。然而,从集合中添加或删除有点棘手。您还需要在关系表中添加一行,并根据所做的操作提交或删除该行

这可以通过传递给这个泛型类的函数来完成吗

这样的类是否存在?如果不存在,它是否可以实现?

很难(甚至不可能)在LINQ to SQL中创建一个感觉像本机的解决方案,因为这样的解决方案必须以以下方式工作:

  • 多集合应建模为其他多实体上的属性
  • 它必须支持插入、更新和删除
  • 它应该在编写LINQ查询时起作用
  • 为第1点制定解决方案很容易。以一个具有
    产品
    类的模型为例,该类与
    订单
    具有多对多关系。您可以在
    Order
    类上定义以下属性:

    public IEnumerable<Product> Products
    {
        get { return this.OrderProducts.Select(op => op.Product); }
    }
    
    不幸的是,此查询将失败,因为LINQ to SQL不知道如何将
    产品
    属性映射到SQL

    当你想这个特性时,你应该考虑迁移到实体框架(4或UP)。EF本机支持这一点。

    很难(甚至不可能)在LINQ to SQL中创建一个感觉像本机的解决方案,因为这样的解决方案必须以以下方式工作:

  • 多集合应建模为其他多实体上的属性
  • 它必须支持插入、更新和删除
  • 它应该在编写LINQ查询时起作用
  • 为第1点制定解决方案很容易。以一个具有
    产品
    类的模型为例,该类与
    订单
    具有多对多关系。您可以在
    Order
    类上定义以下属性:

    public IEnumerable<Product> Products
    {
        get { return this.OrderProducts.Select(op => op.Product); }
    }
    
    不幸的是,此查询将失败,因为LINQ to SQL不知道如何将
    产品
    属性映射到SQL


    当你想这个特性时,你应该考虑迁移到实体框架(4或UP)。EF本机支持此功能。

    您可以创建一个
    IManyToManySet
    接口,该接口可以从多对多属性返回,并具有带有查询插入和删除功能的
    ManyToManySet
    实现

    界面可能如下所示:

    public interface IManyToManySet<TEntity> : IEnumerable<TEntity>
        where TEntity : class
    {
        int Count { get; }
        void Add(TEntity entity);
        bool Remove(TEntity entity);
        void AddRange(IEnumerable<TEntity> collection);
    }
    
    public class ManyToManySet<TSource, TCross, TDestination>
        : IManyToManySet<TDestination>, IEnumerable<TDestination>
        where TDestination : class
        where TSource : class
        where TCross : class
    {
        private TSource source;
        private EntitySet<TCross> crossSet;
        private Func<TCross, TDestination> destinationSelector;
        private Func<TSource, TDestination, TCross> crossFactory;
    
        public ManyToManySet(TSource source, 
            EntitySet<TCross> crossSet,
            Func<TCross, TDestination> destinationSelector,
            Func<TSource, TDestination, TCross> crossFactory)
        {
            this.source = source;
            this.crossSet = crossSet;
            this.destinationSelector = destinationSelector;
            this.crossFactory = crossFactory;
        }
    
        public int Count
        {
            get { return this.crossSet.Count; }
        }
    
        public void Add(TDestination entity)
        {
            var newEntity = this.crossFactory(this.source, entity);
            this.crossSet.Add(newEntity);
        }
    
        public bool Remove(TDestination entity)
        {
            var existingEntity = (
                from c in this.crossSet
                where this.destinationSelector(c) == entity
                select c)
                .SingleOrDefault();
    
            if (existingEntity != null)
            {
                return this.crossSet.Remove(existingEntity);
            }
    
            return false;
        }
    
        public void AddRange(IEnumerable<TDestination> collection)
        {
            foreach (var entity in collection)
            {
                this.Add(entity);
            }
        }
    
        public IEnumerator<TDestination> GetEnumerator()
        {
            return this.crossSet.Select(this.destinationSelector)
                .GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
    
    以及
    产品
    实体中的以下属性:

    private IManyToManySet<Product> products;
    public IManyToManySet<Product> Products
    {
        get
        {
            if (this.products != null)
            {
                this.products = new ManyToManySet<Order, OrderProduct, Product>(
                    this, this.OrderProducts, op => op.Product,
                    (o, p) => new OrderProduct { Order = o, Product = p });
            }
    
            return this.products;
        }
    }
    
    private IManyToManySet<Order> orders;
    public IManyToManySet<Order> Orders
    {
        get
        {
            if (this.orders == null)
            {
                this.orders = new ManyToManySet<Product, OrderProduct, Order>(
                    this, this.OrderProducts, op => op.Order,
                    (p, o) => new OrderProduct { Order = o, Product = p });
            }
    
            return this.orders;
        }
    }
    
    私人IManyToManySet订单;
    公共IManyToManySet命令
    {
    得到
    {
    if(this.orders==null)
    {
    this.orders=new ManyToManySet(
    this,this.OrderProducts,op=>op.Order,
    (p,o)=>neworderproduct{Order=o,Product=p});
    }
    退回此订单;
    }
    }
    
    实际上,
    IManyToManySet
    接口是多余的,因为您可以直接返回一个
    manytomy
    。但是,该接口隐藏了
    TSource
    TCross
    类型参数,这使得该属性的用户更易于阅读

    请注意,此实现具有与LINQ to SQL的
    EntitySet
    相同的加载行为;当使用它时,它会在内存中加载完整的对象集。就像使用
    实体集
    在集合上使用
    where
    First
    一样,仍然从数据库加载完整的集合。你需要意识到这一点

    然而,重要的区别在于LINQtoSQL理解LINQ查询中的
    EntitySet
    属性。在LINQ查询中使用
    IManyToManySet
    ,将会失败得很惨


    我希望这会有所帮助。

    您可以创建一个
    IManyToManySet
    接口,该接口可以从多对多属性返回,并具有带有查询插入和删除功能的
    ManyToManySet
    实现

    界面可能如下所示:

    public interface IManyToManySet<TEntity> : IEnumerable<TEntity>
        where TEntity : class
    {
        int Count { get; }
        void Add(TEntity entity);
        bool Remove(TEntity entity);
        void AddRange(IEnumerable<TEntity> collection);
    }
    
    public class ManyToManySet<TSource, TCross, TDestination>
        : IManyToManySet<TDestination>, IEnumerable<TDestination>
        where TDestination : class
        where TSource : class
        where TCross : class
    {
        private TSource source;
        private EntitySet<TCross> crossSet;
        private Func<TCross, TDestination> destinationSelector;
        private Func<TSource, TDestination, TCross> crossFactory;
    
        public ManyToManySet(TSource source, 
            EntitySet<TCross> crossSet,
            Func<TCross, TDestination> destinationSelector,
            Func<TSource, TDestination, TCross> crossFactory)
        {
            this.source = source;
            this.crossSet = crossSet;
            this.destinationSelector = destinationSelector;
            this.crossFactory = crossFactory;
        }
    
        public int Count
        {
            get { return this.crossSet.Count; }
        }
    
        public void Add(TDestination entity)
        {
            var newEntity = this.crossFactory(this.source, entity);
            this.crossSet.Add(newEntity);
        }
    
        public bool Remove(TDestination entity)
        {
            var existingEntity = (
                from c in this.crossSet
                where this.destinationSelector(c) == entity
                select c)
                .SingleOrDefault();
    
            if (existingEntity != null)
            {
                return this.crossSet.Remove(existingEntity);
            }
    
            return false;
        }
    
        public void AddRange(IEnumerable<TDestination> collection)
        {
            foreach (var entity in collection)
            {
                this.Add(entity);
            }
        }
    
        public IEnumerator<TDestination> GetEnumerator()
        {
            return this.crossSet.Select(this.destinationSelector)
                .GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
    
    以及
    产品
    实体中的以下属性:

    private IManyToManySet<Product> products;
    public IManyToManySet<Product> Products
    {
        get
        {
            if (this.products != null)
            {
                this.products = new ManyToManySet<Order, OrderProduct, Product>(
                    this, this.OrderProducts, op => op.Product,
                    (o, p) => new OrderProduct { Order = o, Product = p });
            }
    
            return this.products;
        }
    }
    
    private IManyToManySet<Order> orders;
    public IManyToManySet<Order> Orders
    {
        get
        {
            if (this.orders == null)
            {
                this.orders = new ManyToManySet<Product, OrderProduct, Order>(
                    this, this.OrderProducts, op => op.Order,
                    (p, o) => new OrderProduct { Order = o, Product = p });
            }
    
            return this.orders;
        }
    }
    
    私人IManyToManySet订单;
    公共IManyToManySet命令
    {
    得到
    {
    if(this.orders==null)
    {
    this.orders=new ManyToManySet(
    this,this.OrderProducts,op=>op.Order,
    (p,o)=>neworderproduct{Order=o,Product=p});
    }
    退回此订单;
    }
    }
    
    实际上,
    IManyToManySet
    接口是多余的,因为您可以直接返回一个
    manytomy
    。但是,该接口隐藏了
    TSource
    TCross
    类型参数,这使得该属性的用户更易于阅读

    请注意,此实现具有与LINQ to SQL的
    EntitySet
    相同的加载行为;当使用它时,它会在内存中加载完整的对象集。就像使用
    实体集
    在集合上使用
    where
    First
    一样,仍然从数据库加载完整的集合。你需要意识到这一点

    然而,重要的区别在于LINQtoSQL理解LINQ查询中的
    EntitySet
    属性。在LINQ查询中使用
    IManyToManySet
    ,将会失败得很惨


    我希望这有帮助。

    好的,我将在下一个项目中使用EF。但我想说的是,我在某种程度上不想成为另一个。基本上,您可以获得关系另一端的对象列表(示例中的产品),并能够直接插入、更新和删除到将自动创建关系的集合。这可以通过将Order类中的函数传递到自定义集合中来实现吗