XmlSerializer can't find EntityObject even though its referenced - entity-framework

I hope that someone can help me with this problem that I've been having with XmlSerializer.
I've already looked through this thread: http://social.msdn.microsoft.com/Forums/en-US/asmxandxml/thread/551cee76-fd80-48f8-ac6b-5c22c234fecf/
The error I am getting is:
System.InvalidOperationException: Unable to generate a temporary class (result=1).
error CS0012: The type 'System.Data.Objects.DataClasses.EntityObject' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Data.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
I've made sure that my unit test has a reference to System.Data.Entity, so it is able to compile at least. I've also in the app.config made an assembly binding to System.Data.Entity.
Here's my rough class structure
[Serializable]
[XmlRoot(Namespace = XmlSupport.MyNamespace, ElementName = XmlSupport.WantToSerialize)]
[XmlInclude(typeof(WantToSerializeBaseClass)]
[XmlInclude(typeof(EntityObject)]
[XmlInclude(typeof(MyEntityObjectSubClass)]
public class WantToSerialize : WantToSerializeBaseClass, IXmlSerializable (I've tried putting this on the baseclass and the current class)
{
// methods and classes
// I've included XmlIncludes for all the classes that this class has a reference too
// even though in the WriteXml it just uses .NET base classes
}
The WantToSerializeBaseClass makes use of some generics, but I've decorated it with XmlIncludes for (EntityObject, and any other classes it makes reference to as well).
the calling code:
var serializerWrite = new XmlSerializer(typeof (WantToSerialize), XmlSupport.ITNNamespace);
fails
However if I do:
var serializerWrite = new XmlSerializer(typeof (WantToSerialize), new Type[] {typeof(EntityObject)});
it is succesfull.
Any thoughts would be most helpful.
UPDATED
I've tracked the problem down to a method in the WantToSerializeBaseClass
public abstract void ConvertFromEntity<TtoCopy>(TtoCopy toCopy) where TtoCopy : MyEntityObjectSubClass;
Where MyEntityObjectSubClass is a subclass of EntityObject, that adds a few methods that I want on my entity objects. The MyEntityObjectSubClass looks like this:
[Serializable]
[XmlInclude(typeof(EntityObject))]
public abstract class MyEntityObjectSubClass : EntityObject, IMyEntityObjectSubClass
Again any thoughts would be great

If you don't have any code that requires a reference at compile time then that reference won't be included in the built assembly. You can use a tool like Reflector to check whether the reference is making it into your assembly.
One thing you can try is adding a static method to WantToSerialize that creates the XmlSerializer. The assembly containing WantToSerialize must already have a good reference to EntityObject, so this should solve the problem.

I have this same problem too (in VB). what I found is that you can use the generic parameter, but it errors because the type MyEntityObjectSubClass is in another assembly. If you remove the type restriction on the generic parameter it will work fine.
I believe this to be an error in the framework itself. I've submitted a feedback ticket to microsoft. I attached a VB.net

I ended up removing the generic code and it worked fine.

I realize this is an older question but for posterity's sake set the CopyLocal parameter on the .dll reference to True.

Related

Autofac RegisterAssemblyTypes tries to resolve all public types

Quick question: I've been using autofac with asp.net core in a project and I've noticed that it tries to resolve all types during configuration after updating it to the latest nuget package (going from Autofac.Extensions.DependencyInjection 5.0.1 to 7.0.2). Btw, here's the code that was being used to register the types:
builder.RegisterAssemblyTypes(typeof(Utilizador).Assembly)
.AsImplementedInterfaces()
.AsSelf();
Until now, I wasn't seeing this behavior. The problem with this new approach is that it will try to resolve types that will never be injected through DI. For instance, it complains about public classes that don't have public constructors event though those classes will never be created through DI.
Can someone point me to when this change happened?
Does this mean that now I must filter the types I need explicitly?
Thanks.
This is nothing new.
You can filter those out with something like below:
builder.RegisterAssemblyTypes(ThisAssembly)
.Where(type => type.GetConstructors(BindingFlags.Public).Any())
.AsImplementedInterfaces();

PostSharp AOP - Unable to apply aspect to mscorlib System.IO.StreamReader members

**I'm using PostSharp Express... not sure that would make a difference in this instance though.
I've got an OnMethodBoundary->OnEntry aspect that successfully multicasts at the assembly level to class members in my own code, but when I attempt to apply it to mscorlib System.IO.StreamReader members, no dice. Based on the searching I've done on the PostSharp web site, here on SO, and on Google, I can't tell what the correct way to go about this is with the current version of PostSharp. Does anyone know? Hopefully I'm just missing something simple :\
Here's the aspect followed by multicast attribute I'm using:
namespace Test.Aspects {
[AttributeUsage(AttributeTargets.Assembly)]
[MulticastAttributeUsage(MulticastTargets.Method, AllowMultiple = false)]
[Serializable]
public class PatchStreamReaderAttribute : OnMethodBoundaryAspect {
public override void OnEntry(MethodExecutionArgs args) {
System.Threading.Thread.Sleep(1000);
}
}
}
[assembly: PatchStreamReader(AttributeTargetMembers = "ReadLine", AttributeTargetAssemblies = "mscorlib", AttributeTargetTypes = "System.IO.StreamReader")]
Usually, when you apply an aspect in a given assembly, PostSharp will modify that assembly during its build process. This, of course, cannot happen for mscorlib or, in fact, for any 3-rd party library you reference but do not build from source code.
This is why PostSharp uses different approach when applying aspects to the referenced assemblies using AttributeTargetAssemblies. Instead of modifying the target 3-rd party assembly, PostSharp will modify the calls from your assembly to the target assembly.
This, of course, gives you less options of where you can inject your code. For example, PostSharp can detect the call to the library's method and inject the aspect around that call. But you cannot inject the aspect around the static or instance constructor of the type from the library.
You also need to pay attention to the AttributeTargetTypes property when applying the aspect. For example, you want to apply the aspect on the calls to the StreamReader.ReadLine() method. This virtual ReadLine() method is originally declared on the TextReader class and StreamReader overrides the method. If you look at the IL, then the method call looks like this:
callvirt instance string [mscorlib]System.IO.TextReader::ReadLine()
This means you need to set AttributeTargetTypes property to "System.IO.TextReader" to apply the aspect to the ReadLine() method.

Entity Framework inheritance over different assemblies

I'm quite new to Entity Framework, but the more I worked with it, the more I actually liked it. But now my passion is at risk, as I'm struggeling with an issue that already made me crush my head against the wall.
The problem is the following:
I'm using Entity Framework 5.0 with code-first approach plus inheritance for my business models represented by Table Per Hierarchy. At first I had all of my entity types, that were supposed to be mapped, in the same assembly as my DbContext (which worked fine for both TPH and TPT). But as they also contain logic that is dependent on other assemblies, this turned out as no good approach since it caused circular dependencies because those assemblies also need to have knowledge of the Data Access Layer, which in turn has to have knowledge of the entity types that it is supposed to map).
I solved this issue by introducing a CommonObjects project, where I now keep all of my abstract classes and stripped out the concrete descendents (containing the logic, etc.) of those base classes into the specific projects, which are responsible for them.
(see: Circular Dependency Solution)
It compiled and everything seemed to fit the way I imagined it.
But now it turned out that Entity Framework seems to struggle with the derivates being in a different assembly than the base classes.
During runtime, when trying to access the DbContext the first time, the compiler threw an InvalidOperationException saying:
The abstract type 'Foo.Bar.AbstractClass' has no mapped descendents
and so cannot be mapped. Either remove 'Foo.Bar.AbstractClass' from
the model or add one or more types deriving from
'Foo.Bar.AbstractClass' to the model.
So EF is obviously not able to find the descendents, as it only knows the base classes (which are in the CommonObjects project), but the descendents are in a different assembly.
DbSet<AbstractClass> AbstractClasses { get; set; }
According to this question:
Entity Framework Code First and Multiple Assemblies
I tried to add the following code to the constructor of my derived DbContext:
((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(
Assembly.Load("Foo1"));
But that did not work for me. While debugging and watching the MetadataWorkspace the method "LoadFromAssembly" did obviously not have any effect on the MetadataWorkspace and its items (no types were loaded from assembly Foo1).
What am I missing here?
Thanks for your answers in advance.
Ben
EDIT: This only barely works and isn't worth it, and doesn't work at all if you're using CodeFirst.
I have encountered the same issue with code first. I tried your method of reflection. This seems a bit wonky, but you can trick EF into being okay with your set up with an internal class.
internal class ClassToMakeEFHappy : AbstractClass {}
I just created that in the same file as my AbstractClass definition and it did the trick.

Entity Framework 5 model first - Where is IDisposable gone?

In Entity Framework 5 model first, there seem to be some breaking changes due to the way the class files are generated (No more code generation, but T4 templates)
2 examples:
The generated context file doesn't implement IDisposable anymore
There isn't a constructor which takes a connectionstring anymore
Are there more breaking changes? And what is the solution to them?
The default code generated from a model in Entity Framework 5 now inherits DbContext instead of ObjectContext.
This still implements IDisposable, but if you're getting an error from a line of code similar to this:
using (var mymodel = new MyModelContext()) { ... }
...complaining about not implementing IDisposable, then your problem is most likely that your model is defined in a separate assembly that references EF5 and you have not added an EF5 reference to your project.
As Ladislav Mrnka has already mentioned in his answer, if you want to pass a connection string to the constructor you have to create your own constructor manually to do this.
If you want to switch Entity Framework back to the older style of generated code, which will automatically generate the constructor you're looking for, then follow these steps:
Click on the designer surface of your EDMX file, and look at the properties window. Find a property called "Code Generation Strategy" and set this to "Default" instead of "None". This will tell Visual Studio to start creating the code for your object model in MyModel.Designer.cs in one big file, this time using ObjectContext instead of DbContext.
Delete the following sub files from below your EDMX file: MyModel.Context.tt, MyModel.tt. These are the auto generated files that you don't want anymore. If you don't delete them you'll get class naming conflicts because your objects will be created twice.
The generated context file doesn't implement IDisposable anymore
IDisposable is still implemented by the parent context type. The generated type is still disposable.
There isn't a constructor which takes a connectionstring anymore
It now uses convention to get connection string but you can add your own constructor either to template or to your partial class part of the context.
Are there more breaking changes? And what is the solution to them?
It is whole breaking change because it uses different API - DbContext API instead of ObjectContext API which means different types, different methods, POCO entities etc. If you want to get back to original code generation you have to delete those T4 templates and enable code generation as described in .Designer.cs file but the current recommended way is to use POCOs and DbContext API.
I was having the same issue with the using statement needing a type that extended IDisposable... Turns out that I forgot to reference System.Data.Entity in my project... Added the reference and it fixed the problem.
Just clean and build the project, don't forget to add the reference to your entity.

Entity Framework Code First and Multiple Assemblies

I have a subclass in a different assembly to its base class. The parent is a POCO class used for EF Code First.
When I try to add an instance of inherited class to the database I get InvalidOperationException: "Object mapping could not be found for Type with identity 'Foo.Bar.MyInheritedClass'".
It works fine if subclass is in same assembly as base class.
In regular EF the solution seems to be a call to ObjectContext.MetadataWorkspace.LoadFromAssembly(assembly). But I can't figure out how this relates to Code First.
Any advice?
I'm using Entity Framework 4.1 RC.
I solved this by inheriting from the first assembliy's DbContext, adding a DbSet<> for the derived class, and then adding new instances of derived type to to that.
Posted code on MSDN forum here.
I know this post is a bit old, but I was able to accomplish this using #Dave's recomendation inside the constructor:
public Context() {
((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace.LoadFromAssembly(
System.Reflection.Assembly.GetAssembly(
typeof(--[Inherited DbContext]--)));
}
I'm quite new to EF (Entity Framework 4) and I got the same exception when I made changes in the model.
My problem turned out to be that I did not know EF need all the names on all the navigation properties to agree, not only their type. For example if there is a navigation property named foo, then there needs to be a declared variable in the corresponding class with the very same name.