Issue in mapping fragments MVC 3 EF Code first - c#

i've recently added a new property to one of my models:
public HttpPostedFile AvailabilityImage { get; set; }
However, upon doing so I'm now getting this very strange error:
error 3004: Problem in mapping fragments starting at line 32:No mapping specified for properties FloorModel.AvailabilityImage in Set Floor
I am at a loss on how to solve this, I've never had this issue adding properties before?
Is it to do with the Data type being used with this property do you think? Any suggestions are welcome
Thankyou

HttpPostedFile is a complex type and contains many aspects to it that cannot be properly serialized. For example, it contains a property that references the current HttpResponseStream. This will be different every time you make a connection, so you can't serialize this.
I doubt what you are trying to do is correct anyways. Are you trying to save the file that is uploaded? If so, then you need to save the actual binary contents.. not the HttpPostedFile.

The framework could of auto-generated a new DbSet with a complex data type. It has happened to me when I'm building models and passing DbSet data types under the model constructor. Go verify the model and remove any complex data types and comment out any DbSet related to that model.
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
.
.
.
public System.Data.Entity.DbSet<Solution.Models.Model1> Model1 { get; set; }
//Comment out possible Model and try debugging again.
//public System.Data.Entity.DbSet<Solution.Models.Model2> Model2 { get; set; }
}

Related

Model with wrong property types

I am new to Entity Framework. I started with database first approach which created my classes corresponding to the tables I selected. I am using WPF. Unfortunately there is a problem occurred while EF6 was mapping classes. The assigned type for a field is byte while in some cases the value exceeds the byte constraints. So, I want to replace it with either int or double. How do I change the model field types without any changes made for the used database?
namespace DataChrome{
public partial class REGISTRY_MEST{
public byte MEST { get; set; } //Wrong typed field
public string MESTNAME { get; set; }
public Nullable<byte> IDSTRAT { get; set; }
public Nullable<int> MESTOLD { get; set; }
}
}
So, giving 7 hours to this problem I found the right solution. All you need is just to set user mapping rules in appconfig file. For more details: visit this page.
The type change should be possible by editing the edmx model: click the MEST property of the class inside the edmx model, then set the Type accordingly in the Properties Window and save the model.
You are running a risk by doing this, as it might be possible to store a value too big for the column if you just change the type this way. You noted that you are using Oracle as the underlying DB, so it might very well be the case that EF generated a "wrong" type for that property.
If you are absolutely sure that the DB will accept the expanded type (int, double) then it should be safe to edit the property as I mentioned at the start. Otherwise you would have to change the DB and generate the class anew - you might need to delete the class from the model and add it again, because not all changes to the table are picked up by the automatic update process.

System.Data.Entity.Core.MappingException, abc in in conceptual side annot be mapped to type 'System.Enum' on the object side

Have spent hours on this error and still couldn't figure out the cause.
System.Data.Entity.Core.MappingException: 'Type 'abc.Database.Enum' in
conceptual side cannot be mapped to type 'System.Enum' on the object
side. Both the types must be abstract or both must be concrete
types.'
What I am doing
use db first approach. db class model is built upon actual database
create a custom dbcontext class based on default dbcontext class. the custom class takes a parameter.
Eg
public class TestDbContext:DbContext
{
public TestDbContext(string connection) : base(connection)
{
}
public DbSet<user_menu> user_menus { get; set; }
}
create a testDBContext object using a database name as argument, find the dbset and change/save the result to a list using ToList().
pass the saved list to view.
The error would throw at step 4.
Things I have tried:
reconstruct the db model class
reconstruct the custom dbcontext class
delete bin/obj folder, clean solution and rebuild.
None of the above methods work.
Hope someone can shed some lights into this one.
Thanks
Cannot believe I spend two days on this. Basically what happened is that there is a typo in one of model of the dbset returned from dbcontext. I accidentally set one of the property in the model to be enum. Changed it back to string type and worked.
The error message is a little bit vague in terms of providing hint on where to look at things but it is a good lesson for me. I found the issue by searching against "enum" against the entire project.

Issue with many-to-many relationship + TPH inhertitance in Entity Framework 6

I am running into an issue with EF6, though I'm fairly sure that this applies to previous versions that support this type of mapping. I fear I know the answer to the question at hand, but I hope that I am doing something wrong, or there is a better workaround than what I present here. All classes are gutted for clarity.
So I have
public abstract class SoftwareFirmware
{
public long Id { get; private set; }
public ICollection<DeviceType> DeviceTypes { get; private set; }
public SoftwareFirmware()
{
DeviceTypes=new HashSet<DeviceType>();
}
}
and
public class DeviceType
{
public long Id { get; set; }
public virtual ICollection<Firmware> AvailableFirmwareVerions { get; private set; }
public virtual ICollection<Software> AvailableSoftwareVerions { get; private set; }
public DeviceType()
{
AvailableFirmwareVerions = new HashSet<Firmware>();
AvailableSoftwareVerions = new HashSet<Software>();
}
}
which as you can see have a many to many relationship defined. I've defined two classes which derive from SoftwareFirmware, the aptly named
public class Firmware : SoftwareFirmware {}
and
public class Software : SoftwareFirmware {}
I'm using Table Per Hierarchy inheritance, so Software and Firmware are stored in the same table with a discriminator column. Finally, I've mapped the relationships in the derived DbContext's OnModelCreating method with
modelBuilder.Entity<DeviceType>().HasMany(d => d.AvailableFirmwareVerions).WithMany(firmware=>firmware.DeviceTypes);
modelBuilder.Entity<DeviceType>().HasMany(d => d.AvailableSoftwareVerions).WithMany(sofware=>sofware.DeviceTypes);
The problem at hand is that Entity Framework does not seem to support inheritance with this mapping, as I receive the following when EF tries to generate the database:
DeviceTypes: FromRole: NavigationProperty 'DeviceTypes' is not valid.
Type 'Software' of FromRole
'DeviceType_AvailableSoftwareVerions_Target' in AssociationType
'DeviceType_AvailableSoftwareVerions' must exactly match with the type
'SoftwareFirmware' on which this NavigationProperty is declared on.
From this I gather that a type that inherits from SoftwareFirmware is not good enough for the NavigationProperty, it must be a SoftwareFirmware type. If I tear the DeviceType collection out of the SoftwareFirmware base class and duplicate it in each of the derived classes, things work, but that's certainly less than ideal.
So finally, my question is- is there another way to configure this so that I can keep my navigation property in my base class? If not, is there a cleaner workaround than what I've described?
UPDATE: so it would seem that SQL Server Management Studio did me wrong, as I had diagrammed out the database previously without the overloaded version of WithMany that takes an expression and it did not include the junction tables. It seems like SSMS doesn't play nice with schema changes in terms adding new diagramming even when the database has been dropped and recreated- it must be restarted. Major pain, but I digress...
As a last ditch effort, I reverted to the parameterless version of WithMany for the mappings, deleted and recreated the database by restarting the application, restarted SSMS, and lo! The junction tables were created. All I needed to do is add an Ignore for the base SoftwareFirmware class's DeviceTypes property and everything generated cleanly. So my FluentAPI mapping code looks like this:
modelBuilder.Entity<DeviceType>().HasMany(d => d.AvailableFirmwareVerions).WithMany();
modelBuilder.Entity<DeviceType>().HasMany(d => d.AvailableSoftwareVerions).WithMany();
modelBuilder.Entity<SoftwareFirmware>().Ignore(s => s.DeviceTypes);
which generates this schema- pretty much exactly the schema I wanted (ignore the extra properties):
However, since the parameterless call to WithMany only hooks up a navigation property on one side, updates to Software.DeviceTypes and Firmware.DeviceTypes aren't tracked by EF so I'm back where I started.
The issue is that you have a single SoftwareFirmware.DeviceTypes property but you are then trying to use it as part of two separate relationships. SoftwareFirmware.DeviceTypes can't be the inverse of both DeviceType.AvailableFirmwareVerions and DeviceType.AvailableSoftwareVerions.
What you're trying to model is a bit strange because you're kind of treating them as distinct relationships, but also not. There are two options here...
Option 1: It's two separate relationships
Remove SoftwareFirmware.DeviceTypes and add a DeviceTypes property on Firmware and Software.
This is actually what you are doing when you put Ignore on the SoftwareFirmware.DeviceTypes property and use the empty overload of WithMany - which is why it works. You're telling EF that there are two relationships (one Software -> DeviceType and the other Firmware -> DeviceType) and that there is no navigation property that points back the other way. Since you ignored SoftwareFirmware.DeviceTypes it's just not part of your model.
Option 2: It's one relationship
Remove the two navigation properties on DeviceType and replace them with a single navigation to the SoftwareFirmware base class. You can always add some façade properties that filter the contents to Software and Firmware (as shown below)
public class DeviceType
{
public long Id { get; set; }
public virtual ICollection<SoftwareFirmware> AvailableVerions { get; private set; }
public virtual IEnumerable<Firmware> AvailableFirmwareVerions
{
get
{
return this.AvailableVerions.OfType<Firmware>();
}
}
public virtual IEnumerable<Software> AvailableSoftwareVerions
{
get
{
return this.AvailableVerions.OfType<Software>();
}
}
public DeviceType()
{
AvailableVerions = new HashSet<SoftwareFirmware>();
}
}
This problem sounds familiar. (checking my email ...yep it was over a year ago!) I had someone send me a sample where a fluent api relationship was failing. They did not have a many to many but I think it's the same problem. I spent a long time looking at it and asked Rowan Miller (on the team) and he said that the fluent api can't comprehend the property coming from the base type.
i.e. the fluent API can't see the DEVICETYPE property when it's looking at AvailableSoftwareVerions or at AvailableFirmwareVersions. (I can't tell you WHY this is. You'd think it could find it via reflection but maybe it just wasn't designed with this scenario in mind.)
This still didn't make sense to me so he explained further (and I'll update his explanation with your types which was a little confusing since you have extra levels of inheritance and things are named a bit inconsistently ...but I
Conceptually the classes don’t really make sense, because a DeviceType
can have many Software(s) or Firmware(s)… but the inverse navigation property is
defined on SoftwareFirmware. So what happens when something that isn’t
a Firmware or Software has a DeviceType? It’s inverse is configured as > DeviceType.AvailableSoftwareVersions
but that can’t work. Even taking EF out of the picture the correct way
to model that is to have the Project property be on Report.
That was with EF5. If my memory is correct and it's the same problem, then maybe it hasn't changed for EF6. Perhaps we should look to see if there's an issue in there for solving this problem. However, his further explanation suggests that it's not a bug but a protection.
(I'm going to ping him to verify that I'm inferring the previous problem to this one correctly).
In that email, Rowan also suggested using getter logic instead of a navigation properties as a workaround.

Using JsonIgnore on serialize, but not on deserialize; confusing with partial models

I've got a Web API project, supported by a MSSQL database containing creation and modified fields on (almost) every table. There are triggers on those fields, such that both are updated when inserting and updating a record, respectively.
Now when I'm serializing the data into JSON after a successful request, I do want to send those creation and modified fields such that the front-end making the request can do their thing with it. What I do not want, however, is that these fields can be modified when the data gets deserialized (or, POSTed back). Quite simple, you would say, just use the [JsonIgnore] attribute on the fields; put it only on the set and not on the get.
Now here is where things start to get confusing for me. All models in my project are automatically generated from an Entity Model (.edmx). As such, I cannot directly edit anything into the models themselves, but I have to generate partial models on top of them. I've seen solutions for this in other SO threads, using the [MetadataType] attribute, like this one here.
But how do I apply this (efficiently) to my case? I've been searching around, but haven't found an example on how to pull apart the auto-implemented properties in a 'higher' partial class. And even so, this would mean that I would have to create partial classes for all my models, which would be quite cumbersome. I can't imagine no-one has ever done this before, so wouldn't there be a more elegant way of pursuing this?
An example of a class would be:
public partial class Person
{
[DataMember]
public Nullable<System.DateTime> Created { get; set; }
[DataMember]
public Nullable<System.DateTime> Modified { get; set; }
}
Eventually I switched from a Model-First approach to a Code-First approach so that I would have much more control over my models.
Though, after searching a lot, I came to answer my own question. The core of this question was that I wanted to be able to set the Created and Modified fields automatically, and ignore the deserialization of the front-end, whilst still being able to send those fields through serialization to the front-end.
The solution lies in overriding the SaveChanges method in the DbContext class. An excellent example of this is given in this SO thread: Entity Framework 4.1 DbContext Override SaveChanges to Audit Property Change. So all courtesy goes to James Pogran for sparking the idea in my head, and solving the problem in that way.
What he does is checking in what way the DbEntity is changed. He sets the Created and Modified fields according to whether the entry is being added or modified, and subsequently calls base.SaveChanges in order to continue normal operations.

Having trouble with Nhibernate and ManyToOne properties

I have a class that has a many to one property defined as follows:
[NHMA.ManyToOne(Name = "TypeOfEvent", ClassType = typeof(EventType), Column="EventTypeId")]
public virtual EventType TypeOfEvent {get; set;}
Everytime I try to load the class using a simple query (just loading all of the events in the database) I get the following exception:
NHibernate.HibernateException :
Creating a proxy instance failed
----> System.Reflection.AmbiguousMatchException
: Ambiguous match found.
The Event table has a foreign key (EventTypeId) that relates to EventType table’s primary key EventTypeId. If I change the mapping to int everything works fine.
I realize this is probably a really simple thing, but googling around hasn’t helped. Help. Please.
I don't think you need to set the Name property on the ManyToOne attribute.
What I've used in past projects has simply been:
[ManyToOne(Column = "TypeOfEvent",
ClassType = typeof(EventType),
NotNull = ??)] // Set as appropriate
public virtual EventType TypeOfEvent { get; set; }
As the commenter mentioned, if you've added other namespaces to that file, the EventType class may be ambiguous; however, if it was, you should get a compiler error.
Is this a new project, or is this the first type of entity you're trying to load? Have you successfully created any other ManyToOne mappings previously in this project?

Categories