通过LINQ基于抽象父属性加载具体子类型

时间:2012-07-17 13:00:35

标签: c# linq entity-framework wcf-data-services odata

我刚搬到的项目有一个抽象类Product,它被选择这样做,因为有4种儿童类型被认为是一种产品并且具有相当大的共性(原因在于组成)。 Product与其关联的ProductType枚举。我需要制作一些与Product相关联的静态功能,例如GetAllProducts()

由于Product表只有通用数据,因此我需要每个ProductType来点击并选择与Product表连接的自己的表信息,因此存在我的问题。 / p>

该模型的后端正在使用EntityFramework + OData,这是一种我不熟悉的技术。

从数据库中获取每个子类型的完全加载数据(以及与之相关的所有通用性)的合适方法是什么,即使我从我的linq中选择它之后我也不知道该类型是什么查询?并且,假设我已经返回了数据,是否有必要通过自己的构造函数打开ProductType来创建实际的子类型?

2 个答案:

答案 0 :(得分:1)

            var result=(
                        from product in context.Products
                        join child1 in context.Child1s
                        on product.ID equals child1.ProductID
                        join child2 in context.Child2s
                        on product.ID equals child2.ProductID
                        join child3 in context.Child3s
                        on product.ID equals child3.ProductID
                        join child4 in context.Child4s
                        on product.ID equals child4.ProductID
                        where product.ID<1000
                        select new {

                                        AnonTypeProduct=product,
                                        AnonTypeChild1=child1,
                                        AnonTypeChild2=child2,
                                        AnonTypeChild3=child3,
                                        AnonTypeChild4=child4,

                        }).ToList();
        IEnumerable<Child1> ch1list=new IEnumerable<Child1>();
        IEnumerable<Child2> ch2list =new IEnumerable<Child2>();
        IEnumerable<Child3> ch3list=new IEnumerable<Child3>();
        IEnumerable<Child4> ch4list=new IEnumerable<Child4>();
        foreach(var result in results)
        {
            Child1 ch1=new Child1();
            ch1=result.AnonTypeChild1;
            ch1.Product=AnonTypeProduct;
            Child2 ch2=new Child2();
            ch2=result.AnonTypeChild2;
            ch2.Product=AnonTypeProduct;
            Child3 ch3=new Child3();
            ch3=result.AnonTypeChild3;
            ch3.Product=AnonTypeProduct;
            Child1 ch4=new Child4();
            ch4=result.AnonTypeChild4;
            ch4.Product=AnonTypeProduct;
            ch1list.Add(ch1);
            ch1list.Add(ch2);
            ch1list.Add(ch3);
            ch1list.Add(ch4);
        }

我希望这会有所帮助。但是,您可以使用Include方法执行此操作。我希望context是ObjectContext或DBContext的对象。

答案 1 :(得分:1)

关于EF + WCF数据服务(OData是协议,WCF DS是OData的Microsoft实现)的很酷的部分是很多这是神奇的。你不需要任何特殊的连接或其他魔法。

以下是一些可以帮助您入门的代码:(我保证,我会在下面介绍它。)

using System;
using System.Data.Entity;
using System.Data.Services;
using System.Data.Services.Common;
using System.ServiceModel;

namespace Scratch.Web
{
    // 4
    [ServiceBehavior(IncludeExceptionDetailInFaults = true)]
    // 1
    public class ScratchService : DataService<ScratchContext>
    {
        static ScratchService()
        {
            // 2
            Database.SetInitializer(new ScratchContextInitializer());
        }

        public static void InitializeService(DataServiceConfiguration config)
        {
            // 3
            config.SetEntitySetAccessRule("*", EntitySetRights.All);
            config.SetServiceOperationAccessRule("*", ServiceOperationRights.AllRead);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
            // 4
            config.UseVerboseErrors = true;
        }
    }

    public class ScratchContextInitializer : DropCreateDatabaseIfModelChanges<ScratchContext>
    {
        protected override void Seed(ScratchContext context)
        {
            base.Seed(context);
            // 5
            context.Products.Add(new DiscontinuedProduct
                                     {
                                         Name = "DP1",
                                         DiscontinuedAt = DateTime.Now.AddDays(-7)
                                     });
            context.Products.Add(new DiscountedProduct
                                     {
                                         Name = "DP1",
                                         Discount = 3.14
                                     });
        }
    }
    // 6
    public class ScratchContext : DbContext
    {
        public DbSet<Product> Products { get; set; }
    }
    // 7
    public abstract class Product
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
    // 7
    public class DiscountedProduct : Product
    {
        public double Discount { get; set; }
    }
    // 7
    public class DiscontinuedProduct : Product
    {
        public DateTime DiscontinuedAt { get; set; }
    }
}

快速演练:

  • 1:在这种情况下,ScratchService是WCF数据服务。它继承自DataService<T>并提供DbContext(EF概念)作为泛型类型。
  • 2:我们使用静态构造函数来设置数据库初始化程序,因为我一直在修改这段代码。
  • 3:我们使服务使用者可以看到实体集和服务操作(不建议使用*/All方法。)
  • 4:我们启用调试(始终有用)
  • 5:我们为数据库播种以获取一些数据
  • 6:我们为EF创建DbContext,并将抽象类Product公开为DbSet。 (请注意,您需要使用WCF DS 5或更高版本才能使用DbContext; WCF DS 5.0.1 [或5.1.0-rc1,如果您是勇敢的]和EF 4.3.1一起使用。)< / LI>
  • 7:我们在根处创建一个带有抽象类的类结构和两个派生类。

请注意,当EF正在播放时,您遵循其规则:   - 我本来可以ProductId没有DataServiceKey属性,EF会把它作为实体的密钥,WCF DS会尊重   - TPT / TPH / TPC均为EF设置   - 如果你想先从数据库中做代码(你可能听起来像这样),那就是download that will help you with that