I'm testing out scaffolding with Entity Framework in Asp.Net MVC 4 (by following this article). I get it to work fine, except that even though my domain object allows null in a field and the database field allows null I get the error message:
Cannot insert the value NULL into column 'IsSuccessful', table 'MyTestProject.Persistence.TestContext.dbo.Prediction'; column does not allow nulls. UPDATE fails.
The statement has been terminated.
My domain object looks like this:
public class Prediction
{
[Key]
public int Id { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Description { get; set; }
public bool? IsSuccessful { get; set; }
}
The generated web page shows IsSuccessful as a drop down box with the choices NotSet, True and False. In the database the column IsSuccessful allows null. Still I get the error message. Everything works fine if I choose True or False (it is saved correctly in the database), but not when I select NotSet.
Surely there must be a way around this?
Some details:
Visual Studio 2012 RC
Asp.Net MVC 4
EntityFramework.dll version 5.0.0.0
That error message looks like it is coming directly from SQL Server. If the server says the column is not nullable, then the column is not nullable. It knows best, after all.
Treble check that the column is really nullable in the database. Also consider:
are you perhaps looking at a different database, with slightly different schema? i.e. one that has not had the correct DDL scripts applied (really easily done)
are you perhaps looking at a different object in the same database? In particular, are you perhaps looking at Halvard.Prediction, where-as the code is looking at dbo.Prediction ?
Related
I have a web api application using sql server EF 6 code first approach and it's up and running.
Now for a table I want to make a column NULL.
From sql server database side I alter my table definition and able to make the column NULL.
But the class definition has [Required] attribute, which is the reason database save (with null value) still failing even I made database column NULL.
[Required]
[StringLength(512)]
public string Name { get; set; }
I there any solution here?
I understand I need to remove [Required] attribute and this requires a code change. I am looking if some way without code change. this is production .
Removing Required attribute
[StringLength(512)]
public string Name {get;set;}
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.
Using : dotnet core 1.1, entity framework code first, sql server.
Is there any elegant way to enable a user working on a large form, represented by a complexe model (40+ tables/C# objects), having multiple "required" fields, to save it's work temporarily and come back to complete it afterward?
Let's say I have this model :
[Table("IdentificationInfo", Schema = "Meta")]
public class IdentificationInfo : PocoBase
{
[...]
public int MetaDataId { get; set; }
[ForeignKey("MetaDataId")]
public virtual MetaData MetaData { get; set; }
public int ProgressId { get; set; }
[ForeignKey("ProgressId")]
public Progress Progress { get; set; }
public virtual MaintenanceInfo MaintenanceInfo { get; set; }
public int PresentationFormId { get; set; }
[ForeignKey("PresentationFormId")]
public PresentationForm PresentationForm { get; set; }
private string _abstract;
[Required]
public string Abstract
{
get { return _abstract; }
set { SetFieldValue(ref _abstract, value, "Abstract"); }
}
[...]
}
[Table("PresentationForm", Schema = "Meta")]
public class PresentationForm : PocoEnumeration
{
[...]
}
The user starts to fill everything (in a big form with multiples tabs or really long page!), but needs to stop and save the progress without having the time to save to fill the PresentationForm part, nor the abstract. Normally, in the database, those fields are not null, so it would fail when we try to save the model. Similarly, it would also fail with EF validation in the UI.
What would be nice is using the Progress property and disable EF model validation (model.isValid()), and also enable database insert even if the fields are null (it is not possible to put default values in those not nullable fields as they are often foreign keys to enum like table).
For the model validation part, I know we can make some custom validator, with custom annotation such as [RequiredIf("FieldName","Value","Message")]. I'm really curious about some method to do something similar in the database?
Would the easy way to do that be to save the model as JSON in a temporary table as long as the progress status is not completed, retrieve it when needed for edition directly from the JSON, and save it to the database only when the status is completed?
To support (elegantly) what you ask you should design it that way.
One table with it's required columns should be minimum segment that have to be inputted before any save. Should make segment optimal size.
You could set all fields to allow null but that would be very BAD design, so I would not consider that option at all.
Now if your input consist of several logical parts, and on form they could be different tabs so each tab is in one table in Db and main table have FKs of others tables.
That FK could be Nullable, and it would enable you to finish say first 2 tabs, Save it, and leave rest for after. So you will know that those FK column that have values are finished(and maybe could be edited still), while others are yet to be inserted. You can also have column Status:Draft/Active/...
What's more this design would allow you to have configurable tabs, so for example based on some chosen selection on main input you could chose what tables can be inputted, and which not and to enable/disable appropriate tabs.
If however you don't want FKs nullable than solution would be some temporary storage, one option being JSON in one string column, as you have mentioned your self. But I see no issues with nullable FKs in this case.
I've looked at lots of other questions on SO but can't get the answer. I have a column in a table called: Sex - Male
I would like to get my hands on whoever named it as it's giving me problems with EF. If I use this:
[Column("Sex - Male")]
public bool Sex { get;set; }
This gives me the error of being incompatible with the model as the field "Sex" could not be found. So I changed to this:
[Column("[Sex - Male]")]
public bool Sex { get;set; }
I then get the message Invalid Column Name [Sex - Male]. Does EF rename columns with spaces in some way as the field does exist and is not any kind of FK?
EDIT
I have found that doing this in the modelBuilder:
modelBuilder.Entity<Student>().Property(x => x.Sex).HasColumnName("Sex - Male");
Causes the same error to appear saying it's incompatible as there is no column called Sex with the same name! I've noticed it occurs on anything I use the Column data annotation for not just this field!
EDIT 2
I created a new application and used a Model Designer to see how it interpreted the column and showed it in the designer as "Sex___Male", however, changing the class to this even with []'s around it still gives me could not find column Sex___Male??
EDIT 3
It appears the error isn't quite what I thought, I found the mapping config works fine when I just use db.Students; and the column is there as expected.
It turns out the area going wrong is this line:
var students = (db as IObjectContextAdapter).ObjectContext.ExecuteStoreQuery<Student>(sql);
So it's clearly the ExecuteStoreQuery that I'm guessing won't use the same mapping configuration therefore sees the column as missing. Not sure why putting the Column annotation on the property in the class doesn't work though??
I have recreated your situation in a test configuration. I was able to succesfully insert and query data using the following configuration
SQL Server 2012
Visual Studio 2013
Entity Framework 6.0.1
If you are using an older version of Entity Framework I would consider updating; that's most likely the cause, however I'm not able to reproduce your environment so this answer is only a guess. I used this code:
Created a table:
create table MyTable2 (
[pk] int not null identity primary key,
[Sex - Male] bit not null);
Class:
public class MyTable2
{
public int pk { get; set; }
public bool Sex { get; set; }
}
Mapping configuration:
this.HasKey(t => t.pk);
this.Property(t => t.Sex).HasColumnName("Sex - Male");
It appears that Entity Framework itself had no issue mapping this column regarding it's normal use however the issue I had is where I was using the ExecuteStoreQuery method to map the model.
It turns out using this means anything you map it to has to have the same names regardless of any data annotations you add on for column (they appear to just get ignored). What I did instead was make a small class with just the fields I needed and changed the sql of the query to Select StudentID As ID, [Sex - Male] As Sex, ...other fields FROM ...etc i.e.
public class StudentReadOnly
{
public int ID { get; set; }
public bool Sex { get;set; }
... other properties
}
And then changed line to:
var students = (db as IObjectContextAdapter).ObjectContext.ExecuteStoreQuery<StudentReadOnly>(sql);
And had no problems. I also found that any properties you put in the class MUST exist in the sql query unlike a usual ef query.
I've a table with 52 columns in my database and I want to write a function to create a row in that table.
In my case, I don't want to use all columns in that table, so I created my model like this.
[Table("CUST_MASTER")]
public class CustomerMaster
{
[Key]
[Column("CUSTOMER_ID")]
public string Id { get; set; }
[Column("CUSTOMER_NAME")]
public string Name { get; set; }
[Column("CUSTOMER_CITY")]
public string City { get; set; }
}
Is there any way to send only this data via Entity framework and set all other not nullable fields to some default data(for strings "", for decimals 0.0, etc.) without writing all that fields in my model and doing it manually?
When you do not incorporate a Table-column in your model then it won't be mapped and it will be totally ignored by all generated SQL.
So the only option is to specify a default value in your Database.
If you set the values in the constructor you will have a default value through your code, but you could look into enabling migrations instead, this way you can set default values. look at this stackoverflow question
I think this old suggestion is what you want. It explicitly mentions the lack of mapping between the conceptual model and the storage model. Not a very popular/understood idea though.
Update: FWIW, this suggests that it is already possible in non-Code-First scenarios.