InvalidOperationException (collection is already set to an EntityCollection) after template modified that all properties are virtual

StackOverflow https://stackoverflow.com/questions/17829797

Question

Default tt for DbContext entities adds in entity's constuctor the initialization code for collection proeprties. Each collection is assigned empty HashSet

For scalar entity properties tt has this code:

public string Property(EdmProperty edmProperty)
{
    return string.Format(
        CultureInfo.InvariantCulture,
        "{0} {1} {2} {{ {3}get; {4}set; }}",
        Accessibility.ForProperty(edmProperty),
        _typeMapper.GetTypeName(edmProperty.TypeUsage),
        _code.Escape(edmProperty),
        _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
        _code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}

if I change it to:

public string Property(EdmProperty edmProperty)
{
    return string.Format(
        CultureInfo.InvariantCulture,
        "{0} {1} {2} {{ {3}get; {4}set; }}",
        AccessibilityAndVirtual(Accessibility.ForProperty(edmProperty)),
        _typeMapper.GetTypeName(edmProperty.TypeUsage),
        _code.Escape(edmProperty),
        _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
        _code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}

Adding AccessibilityAndVirtual() EF starts throwing InvalidOperationException saying that collection is already set to an EntityCollection.

Why do this happen?

UPDATE:

Removing virtual from the PK property removed the exception.

Was it helpful?

Solution

Exception is thrown only if PK property is virtual, so I changed code of Property a little

public string Property(EdmProperty edmProperty, MetadataTools ef)
{
    var acessability = Accessibility.ForProperty(edmProperty);

    return string.Format(
        CultureInfo.InvariantCulture,
        "{0} {1} {2} {{ {3}get; {4}set; }}",
        ef.IsKey(edmProperty) ? acessability : AccessibilityAndVirtual(acessability),
        _typeMapper.GetTypeName(edmProperty.TypeUsage),
        _code.Escape(edmProperty),
        _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
        _code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}

OTHER TIPS

I know this is an old question, but I had the same problem and the answer of @Pavel didn't work for me.

It turned out that When you make all properties virtual, you're implementing Change Tracking Proxies. In this case, The change tracking proxy will override any collection navigation properties and use its own collection type (EntityCollection). That's why you have to cancel any initialization of the navigation properties in the constructors of the classes. ( delete NavigationProperty = new HashSet() in every partial class )

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top