EF Code First collection as ComplexType

时间:2016-02-12 21:05:14

标签: c# entity-framework ef-code-first

For performance reasons I am mapping a set of entities to a view creating a flat table (in a way transforming a TPT inheritance in a TPH). This is to be used only a specific method.

Stack

Is there a way to map the complex_type_collection_properties to a complex property on the materialized object?

e.g.

[view]
id
property1
property2
propertyN
complex_type_collection_property1
complex_type_collection_property2
complex_type_collection_propertyN

Thank you!

1 个答案:

答案 0 :(得分:0)

好的,我创建了example,我假设你的代码中已经有了实体(fromDB变量,让我们想象它是从DB中获取的)或从DB中检索到的实体。比你可以投射每个实体,如下所示。解决方案是全面的,并不复杂。您还应该指定与复杂类型对应的类型参数Normalized<City>(如果您希望将复杂类型更改为另一个,则不需要在转换方法中进行任何更改)。您的复杂属性( City1 City2 等)的名称也必须包含集合属性的名称( City ),它是 - 某些约定。我创建了BaseClass共享属性,我们的两个类来自它(因此你不能将字段从一个类复制到另一个类,而应该将它们放入BaseClass)。此外,您可以拥有唯一的一个集合,即List<T>类型的属性。

public class City
{
    public string Name { get; set; }
    public int Population { get; set; }
}

public class BaseClass
{
    public int id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

public class POCO : BaseClass
{
    public City City1 { get; set; }
    public City City2 { get; set; }
    public City City3 { get; set; }
}

public class Normalized<T> : BaseClass
{
    public List<T> City { get; set; }

    public static explicit operator Normalized<T>(POCO self)
    {
        if (self == null)
            return null;

        var normal = new Normalized<T>();

        foreach (var prop in typeof(BaseClass).GetProperties())
            prop.SetValue(normal, prop.GetValue(self));

        var complexProp = typeof(Normalized<T>).GetProperties().Where(x => x.PropertyType.GetInterfaces().Any(y => y.Name == "ICollection")).First();
        complexProp.SetValue(normal, new List<T>((typeof(POCO).GetProperties().Where(x => x.Name.Contains(complexProp.Name)).Select(x => (T)x.GetValue(self)).ToList())));

        return normal;
    }
}

public static void Main(string[] args)
{
    var fromDB = new POCO
    {
        Age = 20,
        id = 1,
        Name = "Mike",
        City1 = new City { Name = "Moscow", Population = 10 },
        City2 = new City { Name = "London", Population = 20 },
        City3 = null
    };
    var normal = (Normalized<City>)fromDB;
    Console.WriteLine(normal.City.Select(x => x == null ? "EMPTY" : x.Name).Aggregate((a, b) => { return a + ", " + b; }));
}