问题
I know the question already has a solution (eg. this question) but I really can't afford to attach the mapping logic in the same assembly where the domain (POCO classes) is.
Is there any other way?
I found this nice blog post but I couldn't get it working. Here is the model:
public class Institute
{
/**
Code omitted
**/
protected virtual ICollection<InstituteText> InnerInstituteTexts { get; set; }
private InstituteTextSet _TextSets;
public InstituteTextSet Texts
{
get
{
if (_TextSets == null)
_TextSets = new InstituteTextSet(InnerInstituteTexts);
return _TextSets;
}
}
}
Mapping code:
var instituteTextExpression = ObjectAccessor<Institute>.CreateExpression<ICollection<InstituteText>>("InnerInstituteTexts");
institute.HasMany(instituteTextExpression)
.WithRequired()
.HasForeignKey(t => t.InstituteId);
where CreateExpression is defined as:
public static Expression<Func<T, TResult>> CreateExpression<TResult>(string propertyOrFieldName)
{
ParameterExpression param = Expression.Parameter(typeof(T), "propertyOrFieldContainer");
Expression body = Expression.PropertyOrField(param, propertyOrFieldName);
LambdaExpression lambda = Expression.Lambda(typeof(Func<T, TResult>), body, param);
return (Expression<Func<T, TResult>>) lambda;
}
the error I get is:
Initialization method Studentum.Core.Tests.InstituteTests.Initialize threw exception. System.TypeInitializationException: System.TypeInitializationException: The type initializer for 'Studentum.Core.FluentCoreRepositoryFactory' threw an exception. ---> System.InvalidOperationException: The configured property 'InnerInstituteTexts' is not a declared property on the entity 'Institute'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property..
回答1:
The first thing that came to mind is the InternalsVisibleTo assembly attribute. This allows you to name "friend" assemblies that also have access to internal members. I wasn't sure if this would work with EF CodeFirst, but I tried it and it appears to work just fine. You would have to change your model assembly slightly, but I think it is a reasonable change.
You would first need to change your property declaration to protected internal:
protected internal virtual ICollection<InstituteText> InnerInstituteTexts { get; set; }
Then, in your model assembly, add the InternalsVisibleTo
assembly attribute in your AssemblyInfo.cs file with the name of your mapping assembly.
[assembly: InternalsVisibleTo("MappingAssemblyName")]
Finally, you can define your mapping of the property in the mapping assembly like any other publicly accessible property.
institute.HasMany(i => i.InnerInstituteTexts)
.WithRequired()
.HasForeignKey(t => t.InstituteId);
来源:https://stackoverflow.com/questions/5246466/entity-framework-4-mapping-non-public-properties-with-ctp5-code-first-in-a-p