I get the error:
Ambiguous match found
During this code on the .Add
var db = new NexusEntities();
db.Reports.Add(mmr);
From googling it appears to be an issue if the there are two classes with the same name but in different namespaces. As far as I can tell this is not the case... Is there another reason why this error can happen? Or is there a way to tell which parameter it is finding two of?
This is a "weakness" in EF. It happens when the same property appears in class / subtype hierarchy.
Most likely you have a hidden field. i.e. a property that has been redefined.
When EF looks for the a property it too must use the type/base tree to find the property. But if it finds it twice in the tree, it interprets this as a duplicate. EF doesnt just use the lowest most specific override.
So property hiding is not possible with EF.
Check your classes, a property will occur twice somewhere.
Although this is probably a much less likely scenario, but we were running EF Core 1.0 which had only one version of the Include() method... in version 1.1, Microsoft added a second implementation (the string version) and since we were calling this method dynamically we got this error after updating our EF Core to 1.1
Related
I have an issue where I am unable to access the Name object of a range. So, I am calling Excel.Application.get_Range() and passing in a name. It returns a non-null object and I can access methods. However, Range.Name returns a System.__ComObject(). If I try to access Range.Name.Name I get an exception similar to the following
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ''System.__ComObject' does not contain a definition for "Name"
Also, this project is one that I migrated from .net Framework to .net Core. The exact same code works in Framework. I have tried various methods of trying to determine what the underlying type is (because it does not appear to be a Name object). ITypeInfo returns that the typename is Name so it does appear to be a name object.
I'm at a loss as to why I'm unable to access Name.Name in .net core. When I check the .net Core Excel sample they never access a name object.
Also, I am able to access other COM objects like ListObject just fine.
I figured out what the issue is. For anyone else running into this with .net Core, the problem is that .net core appears to not support dynamic types through COM automatically. This is discussed in the following github issue Github issue about dynamic not working. Where it talks about why this doesn't work.
Basically, for my specific case I needed to cast the type manually and then it worked. This also impacts use of IEnumerable COM types needing to be cast directly to IEnumerable before iterating through them.
Assuming you have the following using statement.
using Excel = Microsoft.Office.Interop.Excel;
I had to turn the following:
return range.Name.Name;
into
return ((Excel.Name)range.Name).Name;
As an aside, I also noticed that if you copy/paste the cast above into the debug watch window it does not display properly and instead shows an exception about an invalid cast.
For my specific context I control the target classes. They were auto-generated based on XSDs and have huge overlaps because they represent different versions of the same class.
Each version is a huge C# class of over 5.000 lines.
Support can't be dropped for old versions. This means we always need to be able to map the domain class to several different versions and back again. There are always small but breaking changes from version to version. More than 90% of the target class is always the same, even if the code is duplicated for each version.
Currently there is one big mapping for each format, which is a horror. There is so. much. duplicated. code. Furthermore, developers tend to make updates where they need it, and skip everything else, which means individual versions often go out of sync, meaning that one version will be updated to do something that other versions don't. This is also not ideal.
So my question to you is: What strategy can you use for this kind of mapping?
Given the size of your classes, and having to maintain multiple versions, I'd suggest serializing and serializing. Assuming that they otherwise approximate one another, JsonConvert doing JsonConvert.Deserialize<TargetClass>(JsonConvert.Serialize(sourceClass)) should solve it, though I've not worked with such large models to have any idea on how performant it is.
Alternatively, you could use a t4 template (if you're not in .net Core anyway) to generate the mapping using reflection into a common method or whatever.
As far as preventing the Developer problem... Interfaces, base classes that define as much of this centrally as possible. Code reviews to ensure that developers are making changes to the lowest layer they possibly can.
You can do some tricky things with inheretence with static using statements, I'm pretty sure.
Something dumb like
using OldVersion = path.to.the.class.CantRenameThis;
class CantRenameThis : OldVersion
We ended up with a solution that achieved the main targets:
Decent compile-time safety to spot mapping errors
De-duplication of code
No messing with the auto-generated code
We did this by exploiting that the auto-generated classes are generated as partial. That means we can extend them.
We ended up creating hierarchies of interfaces/classes looking like this:
ClassV1 implements IClassVerySpecificV1
ClassV2 implements IClassVerySpecificV2
IClassVerySpecificV1 implements SpecificA, SpecificB, SpecificC and IClassBasic
IClassVerySpecificV1 implements SpecificB, SpecificC, SpecificD and IClassBasic
A mapper would then look like:
ClassV1Mapper requires a SpecificAMapper, SpecificBMapper, SpecificCMapper and ClassBasicMapper
ClassV2Mapper requires a SpecificBMapper, SpecificCMapper, SpecificDMapper and ClassBasicMapper
This way we could map 90% of everything by just throwing everything that belongs to IClassBasic into a ClassBasicMapper.
We did run into some issues however:
As you can already guess, we end up with a LOT of interfaces. More than you want.
Sometimes a field exists across versions, but has different (enum) values. Our domain model would have the superset, with an attribute specifiying which values were valid for which versions.
Just trying to confirm an impression: it seems enums in EF5 + Code First are only supported when declared within the same namespace as the classes using them as property types.
Can anyone confirm that? Couldn't find anything on the web for this...
A relevant bug that was fixed earlier. 4.3 Beta 1 release notes say:
Bug fix for GetDatabaseValues. In earlier releases this method would
fail if your entity classes and context were in different namespaces.
This issue is now fixed and the classes don’t need to be in the same
namespace to use GetDatabaseValues.
My guess is that GetDatabaseValues function is still buggy for this occasion (but that's just an educated guess). You may want to report this here: ADO.NET team blog: EF5 Beta 1 Available
Not only do your enumerations have to be in the same namespace to be supported by EF5 Code First, they have to be in the same class file as your POCO Model.
I just discovered I get no errors if there is no mapping to a property if the source has a property with the same name. We are trying to make it as strict as possible and get errors when there are unmapped properties. It seems like Assert.IsConfigurationValid() doesn't do that. Is there a way to make it work with stricter control?
I dont believe that there is. I had a similar problem on a recent project.
What we did was ensure that every property on the target was specified in the mapping configuration in alphabetical order. Even if it was being ignored.
When errors occured it was possible to do a "visual" check of the target to see if any properties had been added / missed.
I'm trying to use protobuf .net to serialize an instance of a class which is inherited from a base class. When trying to serialize\deserialize i'm getting an exception about "type not expected". As I already read, adding the protoinclude with the derived type to the base wil solve the problem. BUT, my problem is that I can't add the attribute, since I don't know the types that will derive my base. As I already read, I understand that V2 is going to provide a way to define a type model in order to describe inheritance. So my questions are:
When V2 release will be avilable?
Is there a workaround in the mean time to solve this issue?
Thanks in advance,
Gil
V2 is available both from nuget and google-code (nuget is a few revs ahead IIRC - and both are a little behind the head). There are a few v1 features not yet re-implemented, but for most purposes you won't notice this. They will be re-added in due course.
Re your problem; that is available via MetaType.AddSubType - however, to use that approach you must be able to reproduce the same int identifiers per-subtype in the future - they are important keys and must not change.
RuntimeTypeModel.Default[typeof(SomeType)].AddSubType(7, subType);
There is also DynamicType available on "object" properties - however this has a few kinks with inheritance-based models; I would avoid that for now (this too will be rectified shortly).