Object Mapping not found ...
I have perused the samples and created a project from scratch using the JuneCTP EF and I believe I get it (they are working fine). However, I am attemping to prototype a solution using our existing types mapped through EF to our database. An important note: we have multiple levels of inheritance which goes across namespaces. I do not think this is causing my current issue, but there it is.
I am receiving the following exception when I attempt to read the first UserLogin object from my datastore:
System.InvalidOperationException: Object Mapping could not be found for Type with identity 'MyCompany.Types.UserContext.UserLogin'.
at System.Data.Mapping.DefaultObjectMappingItemCollection.GetMap(GlobalItem item)
at System.Data.Metadata.Edm.MetadataWorkspace.GetMap(GlobalItem item, DataSpace dataSpace)
at System.Data.Objects.ObjectMaterializer.GetObjectMapping(TypeUsage typeUsage)
at System.Data.Objects.ObjectMaterializer.LookupObjectMapping(TypeUsage typeUsage)
at System.Data.Objects.ObjectMaterializer.VerifyType[T](TypeUsage typeUsage)
....
Here is the fragment from my CSDL file describing this object:
<
SchemaNamespace="MyCompany.Types.UserContext"Alias="Self"xmlns="http://schemas.microsoft.com/ado/2006/04/edm"><
EntityContainerName="MyCompanyDataSource"> <
EntitySetName="userLoginMap"EntityType="MyCompany.Types.UserContext.UserLogin" /> </
EntityContainer> <
EntityTypeName="UserLogin"><
Key><
PropertyRefName="ID" /></
Key><
PropertyName="ID"Type="Int32"Nullable="false" /><
PropertyName="OrganizationID"Type="Int32"Nullable="false" /><
PropertyName="Login"Type="String"Nullable="false"MaxLength="100"Unicode="false" /></
EntityType>...
Here is the fragment from my MSL file providing the mapping to the store:
<
MappingSpace="C-S"xmlns="urn
chemas-microsoft-com:windows
torage:mapping:CS"><
EntityContainerMappingStorageEntityContainer="dbo"CdmEntityContainer="MyCompanyDataSource"> <
EntitySetMappingName="userLoginMap"StoreEntitySet="userLogin"TypeName="MyCompany.Types.UserContext.UserLogin"><
ScalarPropertyName="ID"ColumnName="userLoginID" /><
ScalarPropertyName="OrganizationID"ColumnName="organizationID" /><
ScalarPropertyName="Login"ColumnName="userLogin" /></
EntitySetMapping>...
Here is the fragment from my SSDL file describing the store:
<
SchemaNamespace="MyCompanyDatabase"Alias="Self"xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl"><
EntityContainerName="dbo"> <
EntitySetName="userLogin"EntityType="MyCompanyDatabase.userLoginStore" /> </
EntityContainer> <
EntityTypeName="userLoginStore"><
Key><
PropertyRefName="userLoginID" /></
Key><
PropertyName="userLoginID"Type="int"Nullable="false"StoreGeneratedPattern="identity" /><
PropertyName="organizationID"Type="int"Nullable="false" /><
PropertyName="userLogin"Type="varchar"Nullable="false"MaxLength="100" /></
EntityType>...
Here is the code used to construct the query (database connection information is in the web.config file):
[ObjectContext]
.CreateQuery<UserLogin>("userLoginMap"); What am I missing? The query construction is the same as in the Northwind sample and my first prototype (for which I used all of the auto-generated mapping files and classes -- but I need to use our current class types, not auto-generated ones; yes, I have all the necessary attributes). Have I crossed some wires in the mapping configurations?
An interesting thing I found during my playing: if I remove the Nullable="false" attribute from the CSDL files' OrganizationID property, the EF complains when it verifies the files (since the column is not nullable in the SSDL file). So I believe it is seeing the relationships ... it's just not mapping.
My guess is that EntityLogin and UserLogin are in different CLR assemblies. I think the EF runtime is not finding the assembly that has UserLogin type. We find the metadata for types as long as they are in the same assembly as the type for ObjectQuery<T> comes from. So UserLogin must be in a Assembly that does not fall in either of these buckets.
The way to make this work is to load the metadata before hand for this Assembly.
You can call the following method to load the metadata,
ObjectContext.MetadataWorkspace.LoadFromAssembly(Assembly assembly) where assembly is the CLR assembly that has UserLogin type.
Thanks
Srikanth
Nope ... no other assembly is being used. The Types .cs files are included in the App_Code of the service project directly. Since Orcas Express JuneCTP only lets me create web projects (not assemblies), I created a new WCF Service and copied over my Types, adding the attributes to the classes and properties necessary for the EF.
The class which is creating the query, while in the same WCF Service project, is in a different namespace than the Types (MyCompany.DataSource.Builder.SvcContext) -- could that be contributing to this issue?
Another question that is somewhat related due to my inheritance structure: the EDM tech preview document (granted it's a year old) refers to the ability to reference another namespace in the CSDL that might contain a base type for your object:
<using Namespace="MyCompany.Types.Base" />
However, the "using" node is invalid in the current schema. The UserLogin class is about 4 levels deep in our inheritance structure; is it necessary, in the current CTP of the EDM, to define such a structure in the mapping files? If so, how is this accomplished? It is possible to have multiple CSDL files, defining the namespaces and their classes and referencing those namespaces in the main "working" class that is actually mapped?
(P.S.: I corrected the object query line which incorrectly used the EntityLogin object -- it is actually UserLogin object. Typo - my bad.)
I don't think the fact that the class that is creating the query is in different namespace than the other types should matter. When you use, CreateQuery<T>, we pick up the Object space metadata for T and all types in the assembly that T comes from by default. So I am not sure why the system is complaining about Object Mapping for UserLogin type. I have seen this exception before when the CLR type was not in the scope for our runtime. But in this case, since you have used CreateQuery<T> for UserLogin type, we should have picked up the metadata for UserLogin type. So at this point I don't know why this would be happening. Since you have mentioned that you have attributed the class manually, there could be some problem there. But again I am not sure.
Regarding the other question, We will add support for "Using" in Beta2.
Thanks
Srikanth
Thanks for pointing me at my self-attributed class; I have reviewed it and found some abnormalities and corrected them -- and it's still not finding my mapping (same exception).
Here is my (annotated) class file to demonstrate its attributes and properties. During testing, I am attempting to break my working prototype by changing elements to make it match my non-working integration. I can neither break the working prototype nor get my integration working. I am going cross-eyed from looking across all of these files (double-checking my mappings, the classes, builder, etc) and would appreciate another set of eyes reviewing my code.
namespace
MyCompany.Types.UserContext {
[System.Runtime.Serialization.
DataContractAttribute()] [System.Data.Objects.DataClasses.
EdmEntityTypeAttribute()] public class UserLogin: System.Data.Objects.DataClasses.EntityObject {
#region
Protected Members
protected string _login= string.Empty;
protected int _organizationID = 0; protected int _objectID = 0;
#endregion
#region
Public Properties
[System.Runtime.Serialization.DataMemberAttribute()]
[System.Data.Objects.DataClasses.
EdmScalarPropertyAttribute(IsNullable = false)] public string Login {
... }
[System.Runtime.Serialization.DataMemberAttribute()]
[System.Data.Objects.DataClasses.
EdmScalarPropertyAttribute(IsNullable = false)] public int OrganizationID {
... }
[System.Runtime.Serialization.DataMemberAttribute()]
[System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty = true, IsNullable = false)]
public int ID
{
...
}
#endregion
}
}
I have a "builder" class that inherits from System.Data.Objects.ObjectContext and whose constructor sets the database connection and entity container to "MyCompanyDataSource". I then create the query (as stated in my first post). When I attempt to get the first record, the query's results throws the exception.
I have tried re-setting IIS after every change, removing all inheritance, modifying namespaces and everything else I can think of with no success. I can't even break my working prototype. Is there anything else I need to check as I created the mapping files with the tool, but modified them to work with my existing Types class?
Any thoughts, suggestions or caveats are most welcome!
The exception you mentioned previously is not related to Custom mappings. It's related to object space metadata. Can you add the following Assembly attribute to the top of your code you pasted above and see if it helps.
[assembly: global:
ystem.Data.Objects.DataClasses.EdmSchemaAttribute()]
Thanks
Srikanth
Thanks! That did it! I have even moved this piece to the main Service class and verified that it works as well (and as all my service classes inherit from a common base, this solution will not hamper me).
I find it a little odd that my working prototype, which used the tool to create the mapping files and the classes, does not have this notation and works fine. But, this works and you have made me a happy developer. Thanks again!