Linq并加入不同的房产

时间:2016-02-16 13:43:58

标签: c# entity-framework linq reflection

我想通过linq加入一些实体。问题是我想加入的财产是动态的。例如:

product_id = 1

例如在我的AClass表中将存储" n" - 元素,每个元素可以有不同的源映射,其中存储了字符串数据。

{ColumnDesc = "x" and ColumnMappingName = "String_Value_1"}将有映射product_id = 2

//这意味着财产的价值" x"在String_Value_1

列中存储此产品

{ColumnDesc = "x" and ColumnMappingName = "String_Value_2"}将有映射product_id = 3

//这意味着财产的价值" x"在String_Value_2

列中存储此产品

{ColumnDesc = "x" and ColumnMappingName = "String_Value_3"}将有映射product_id = 4

//这意味着财产的价值" x"在String_Value_3

列中存储此产品

{ColumnDesc = "x" and ColumnMappingName = "String_Value_1"}将有映射{{1}}

//这意味着财产的价值" x"在String_Value_1

列中存储此产品

我想要做的是获取已定义CoulmnDesc的AClass对象的所有值(来自BClass)。我不想通过3个查询(字符串列可以是10或甚至更多)来执行它,而是通过使用lambda expresions通过属性名称或反射来动态地执行它

1 个答案:

答案 0 :(得分:0)

这应该是您问题的正确解决方案,不要担心大量记录,SQL Server会找到一种方法来快速获取数据。

    public class AClass
    {
        public int Id { get; set; }
        public string Name { get; set; }

        [ForeignKey("AClassId")]
        public virtual List<PropertyValue> PropertyValues { get; set; }
    }
    // Id = 1, Name = "P1"
    // Id = 2, Name = "P2"
    // Id = 3, Name = "P3"

    public class PropertyValue
    {
        public int Id { get; set; }

        public int AClassId { get; set; }
        [ForeignKey("AClassId")]
        public virtual AClass A { get; set; }

        public int PropertyNameId { get; set; }
        [ForeignKey("PropertyNameId")]
        public virtual PropertyName PropertyName { get; set; }

        public string Value { get; set; }
    }
    // Id = 1, AClassId = 1, PropertyNameId = 1, Value = "p1 x1 y1"
    // Id = 2, AClassId = 1, PropertyNameId = 2, Value = "p1 x2 y2"
    // Id = 3, AClassId = 1, PropertyNameId = 3, Value = "p1 x3 y3"

    // Id = 4, AClassId = 2, PropertyNameId = 2, Value = "p2 x2 y2"
    // Id = 5, AClassId = 2, PropertyNameId = 3, Value = "p2 x3 y3"
    // Id = 6, AClassId = 2, PropertyNameId = 4, Value = "p2 x4 y4"

    // Id = 7, AClassId = 3, PropertyNameId = 3, Value = "p3 x3 y3"
    // Id = 8, AClassId = 3, PropertyNameId = 4, Value = "p3 x4 y4"
    // Id = 9, AClassId = 3, PropertyNameId = 5, Value = "p3 x5 y5"

    public class PropertyName
    {
        public int Id { get; set; }
        public string Name { get; set; }

        [ForeignKey("PropertyId")]
        public virtual List<PropertyValue> PropertyValues { get; set; }
    }
    // Id = 1, PropertyName = "x1"
    // Id = 2, PropertyName = "x2"
    // Id = 3, PropertyName = "x3"
    // Id = 4, PropertyName = "x4"
    // Id = 5, PropertyName = "x5"

    public void DoStuff()
    {
        List<AClass> productlist = new List<AClass>();

        foreach (var product in productlist)
        {
            var productname = product.Name;

            foreach (var property in product.PropertyValues)
            {
                var propertyname = property.PropertyName.Name;
                var propertyvalue = property.Value;
            }
        }
    }

[编辑]

您的原始解决方案是可行的,我将向您展示&#34;学习目的&#34;。

    public class AClass
    {
        public int Id { get; set; }
        public string Name { get; set; }

        [ForeignKey("AClassId")]
        public virtual List<PropertySet> PropertySets { get; set; }
    }

    public class PropertySet
    {
        public int Id { get; set; }

        public int AClassId { get; set; }
        [ForeignKey("AClassId")]
        public virtual AClass A { get; set; }

        public int PropertyNameId_Column1 { get; set; }
        [ForeignKey("PropertyNameId_Column1")]
        public virtual PropertyName PropertyName_Column1 { get; set; }
        public string Value_Column1 { get; set; }

        public int PropertyNameId_Column2 { get; set; }
        [ForeignKey("PropertyNameId_Column2")]
        public virtual PropertyName PropertyName_Column2 { get; set; }
        public string Value_Column2 { get; set; }

        public int PropertyNameId_Column3 { get; set; }
        [ForeignKey("PropertyNameId_Column3")]
        public virtual PropertyName PropertyName_Column3 { get; set; }
        public string Value_Column3 { get; set; }
    }

    public class PropertyName
    {
        public int Id { get; set; }
        public string Name { get; set; }

        [ForeignKey("PropertyNameId_Column1")]
        public virtual List<PropertySet> PropertySets_Column1 { get; set; }

        [ForeignKey("PropertyNameId_Column2")]
        public virtual List<PropertySet> PropertySets_Column2 { get; set; }

        [ForeignKey("PropertyNameId_Column3")]
        public virtual List<PropertySet> PropertySets_Column3 { get; set; }
    }

我添加了此解决方案,因此您可以了解如何在EF中进行多重映射。 (想想:AddedByUser,UpdatedByUser等。)请不要使用这种方法来解决你的问题,这将是一个不好的做法和很多工作。

[/编辑]

[EDIT2]

在我以前工作的公司里,我有这个同事说完全一样的东西(&#34;这个系统不适用于数百万条记录&#34;)。他制定了一些比特方式的比较方法来映射他预定义的属性。这个系统确实使用了1.000.000+记录,但我从来没有花时间正确地反驳他的方法。

你现在将成为我的受害者;)哈哈

我目前正在使用5.000.000产品创建测试环境。每个产品都分配了3个值,创建了一个15.000.000记录的值表。

enter image description here

[/ EDIT2]

[EDIT3]

好的,这是出乎意料的,我做了2次测试:

查询1.选择随机1.000.000产品

SELECT TOP 1000000 *
  FROM [test].[dbo].[products]
  ORDER BY NEWID()

查询2.选择随机1.000.000产品,内部连接属性

SELECT TOP 1000000 *
  FROM [test].[dbo].[products] p
  INNER JOIN [test].[dbo].[View_1] v
  ON v.ProductId = p.Id
  ORDER BY NEWID()

猜测结果:

查询1:3执行4秒

查询2:7执行8秒

启用外键和主键时的结果完全相同。我希望SQL服务器完全能够在内存中处理10.000.000,数据库只有2 gig的大小。

因为&#34;完美&#34;存储信息的方式数据库可以使用引擎盖下的各种优化(因为INNER JOINS)非常容易查询。如果我只选择1个产品,结果会很快,计时器会保持在0:00。

[/ EDIT3]