InvalidOperationException: The property is part of the object's key information and cannot be modified - entity-framework-4

I'm getting this error when I try to change column value.
Here is how I got to this problem:
1) I was needed to add this bit column to an Existing table.
ALTER TABLE BooksDB.dbo.Books
ADD edited bit NOT NULL DEFAULT(0),
2) Updated my EF model in project.
3) Now when I try to change 'edited' property of entity object, I'm getting the error from Subject line.
Why is that?
EF object declaration:
/// <summary>
/// No Metadata Documentation available.
/// </summary>
[EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
[DataMemberAttribute()]
public global::System.Boolean edited
{
get
{
return _edited;
}
set
{
if (_edited != value)
{
OneditedChanging(value);
ReportPropertyChanging("edited");
_edited = StructuralObject.SetValidValue(value);
ReportPropertyChanged("edited");
OneditedChanged();
}
}
}
private global::System.Boolean _edited;
partial void OneditedChanging(global::System.Boolean value);
partial void OneditedChanged();

This problem solved by adding PRIMARY KEY to the table.

Related

Validation of fields on indexers

I'm creating a new message, by setting the indexers, like:
Iso8583 isoMsg = new Iso8583();
isoMsg[field] = value;
I noticed that I'm not receiving any exceptions; following the code I've seen that the validator is not running when I'm setting the fields this way; it only executes when unpacking a byte[] message. Do you think it would be possible to adapt the format and length validators to run also when setting a field?
Thanks in advance!
The validators are run on the fields when you call .Pack() on the message.
I guess you just set the value to one of the existing fields form the default template
When you create Iso8583() it uses the DefaultTemplate, which adds the set of default fields into the message instance on creation.
Indexer property is derived from AMessage class, which is Iso8583 class is inherited from.
public string this[int field]
{
get { return this.GetFieldValue(field); }
set { this.SetFieldValue(field, value); }
}
These methods:
protected string GetFieldValue(int field)
{
return this.bitmap[field] ? this.fields[field].Value : null;
}
protected void SetFieldValue(int field, string value)
{
if (value == null)
{
this.ClearField(field);
return;
}
this.GetField(field).Value = value;
}
So it seems that your code sets the value for one of the field from the default template
isoMsg[field] = value;

MVC c# ViewModel with table object

I have a viewmodel as such
public class NoteViewModel
{
public tblNotes tblnote { get; set; }
}
In my controller, I do the following next after doing a build so my controller knows about the viewmodel:
NoteViewModel viewModel= new NoteViewModel();
viewModel.tblnote.NoteModeID = 1234; // get error here
return PartialView(viewModel);
I get the following error though:
{"Object reference not set to an instance of an object."}
What is the type tblNotes? (Side note: In C# class names should begin with a capital letter as a matter of convention.)
Since this is a custom type and, thus, a reference type, its default value is null. So when you instantiate a new NoteViewModel it's going to set all of its members to their default values unless otherwise specified. Since that value is null, you can't use it here:
viewModel.tblnote.NoteModeID = 1234;
Without knowing more about your types, the simple answer is to just instantiate that member in the view model's constructor:
public class NoteViewModel
{
public tblNotes tblnote { get; set; }
public NoteViewModel()
{
tblnote = new tblNotes();
}
}
This way the object will be instantiated any time a view model is created, so you can use it.
What exactly is tblNotes? If it is a reference type, than viewModel.tblNote is null after the first line of code is executed.

Error getting foreign key data on entity

I'm new in MVC2 and Entity Framework and I tried get a list of products with the respective category name, but it's returned me the error
"Object reference not set to an instance of an object."
I have a table Product with a foreign key Category.
I'm using MVC2 and Entity Framework 4.0.
public class Repository
{
public IQueryable<Produto> ListAllProducts()
{
return entities.Produtos;
}
}
public class AdminProdutoController : Controller
{
TudoDeMassinhaRepository repository = new TudoDeMassinhaRepository();
public ActionResult Index()
{
var produtos = repository.ListAllProducts().ToList();
return View(produtos);
}
}
code in view where the error is generated: <%: item.CatProduto.cat_produto_nome%>
You're only selecting the products - you're not currently including the categories. This means: you'll get back your product objects, but any related objects they refer to are not loaded automatically - that's why the .CatProduto property will be NULL and thus you're getting the error.
You need to explicitly specify which additional entities you want to have loaded - something like:
public IQueryable<Produto> ListAllProductsWithCategories()
{
return entities.Produtos.Include("CatProduto");
}
This way, you should get back your Produto objects, and their CatProduto property should have been loaded and populated, too.
So if you change your index method to be:
public ActionResult Index()
{
var produtos = repository.ListAllProductsWithCategories().ToList();
return View(produtos);
}
it should work.

Entity Framework 4: PropertyChanged event is raised too often

the generated code from EF for a property of an entity looks like this:
/// <summary>
/// No Metadata Documentation available.
/// </summary>
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
public global::System.DateTime DateCreated
{
get
{
return _DateCreated;
}
set
{
OnDateCreatedChanging(value);
ReportPropertyChanging("DateCreated");
_DateCreated = StructuralObject.SetValidValue(value);
ReportPropertyChanged("DateCreated");
OnDateCreatedChanged();
}
}
private global::System.DateTime _DateCreated;
partial void OnDateCreatedChanging(global::System.DateTime value);
partial void OnDateCreatedChanged();
This code doesn't check if the value has actually changed (in the setter). Therefore the PropertyChanged event is raised even if you set a value that is equal to the current value. But in this case nothing would have changed, so I wouldn't want this event...
For EntityKey properties they do check this:
/// <summary>
/// No Metadata Documentation available.
/// </summary>
[EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
[DataMemberAttribute()]
public global::System.Guid Id
{
get
{
return _Id;
}
set
{
if (_Id != value)
{
OnIdChanging(value);
ReportPropertyChanging("Id");
_Id = StructuralObject.SetValidValue(value);
ReportPropertyChanged("Id");
OnIdChanged();
}
}
}
private global::System.Guid _Id;
partial void OnIdChanging(global::System.Guid value);
partial void OnIdChanged();
I would expect this behavior from all properties.
Am I missing a setting in the model designer, or is there another solution?
Thanx!
It is point of T4 templates to allow you modifications you need. It is absolutely wrong approach to say:
But I would rather not use a custom template in my project!
It is like throwing all advantages of T4 templates away and going back to hardcoded custom tools for code generating.
I did, as I knew it was possible and Ladislav also stated, include the T4 template file into the project and made the following changes to the "Write PrimitiveType Properties." part of the template:
if (!Object.Equals(<#=code.FieldName(primitiveProperty)#>, value))
{
<#=ChangingMethodName(primitiveProperty)#>(value);
ReportPropertyChanging("<#=primitiveProperty.Name#>");
<#=code.FieldName(primitiveProperty)#> = StructuralObject.SetValidValue(value<#=OptionalNullableParameterForSetValidValue(primitiveProperty, code)#>);
ReportPropertyChanged("<#=primitiveProperty.Name#>");
<#=ChangedMethodName(primitiveProperty)#>();
}
Hope that will be helpfull to others.

Update a row in ASP.NET and MVC LINQ to SQL

I have a simple row that has 4 columns:
{ [Primary Key Int]RowID, [text]Title, [text]Text, [datetime]Date }
I would like to allow the user to edit this row on a simple page that has a form with the fields "Title" and "Text".
There is a hidden field to store the RowID.
When the user posts this form to my controller action, I want it to update the row's Title and Text, and keep the Date the same. I don't want to have to explicitly include a hidden field for the Date in the form page.
Here is my action:
[AcceptVerbs(HttpVerb.Post)]
public ActionResult EditRow(Row myRow)
{
RowRepository.SaveRow(myRow)
return View("Success");
}
RowRepository:
public void SaveRow(Row myRow)
{
db.MyRows.Attach(myRow);
db.Refresh(RefreshMode.KeepCurrentValues, myRow);
db.SubmitChanges();
}
This dosen't keep the "Date" value already in the row and tries to insert a value that throws an timespan exception.
How can I just tell it to keep the old values?
I tried doing RefreshMode.KeepChanges and nothing.
I'm not in a position to test this at the moment but try making the datetime column nullable and then ensure that the datetime passed into SaveRow has a null value.
Try
[AcceptVerbs(HttpVerb.Post)]
public ActionResult EditRow([Bind(Exclude="Date")] Row myRow) {
RowRepository.SaveRow(myRow)
return View("Success");
}
Update
Try this approach, where there is no 'Date' field on your page
[AcceptVerbs(HttpVerb.Post)]
public ActionResult EditRow(int RowID) {
Row myRow = RowRepository.GetRow(RowID);
UpdateModel(myRow);
RowRepository.Save();
return View("Success");
}
In your repository
public void Save() {
db.SubmitChanges();
}
This will only save the changes made to 'myRow'
You will have add a method in the partial class / override the code it build.
The class Table does implement "INotifyPropertyChanging|ed" which is used to track which column has been changed.
You can hack it and reset the value "this.PropertyChanged".
But what I do at work is a stupid READ-APPLY-WRITE approach (and I am using WebForm).
public void SaveRow(Row myRow)
{
var obj=db.MyRows.Where(c=>c.id==myRow.id).First();
obj.a=myRow.a;
obj.b=myRow.b;
db.SubmitChanges();
}
You can do a bit simpler.
public void SaveRow(Row myRow)
{
db.MyRows.Attach(new Row(){
Id=myRow.Id,
Title=myRow.Title,
Text=myRow.Text,
});
db.SubmitChanges();
}
PS. I am new to LINQ to SQL. Please let me know if there is a smarter way to do it.
Ok, I set it to nullable and it keeps overwriting the database as a null value. I guess its impossible to do this since technically null is a valid value for the column and if I pass an object to the function, the empty values must contain something or be null.
So I would have to explicitly state to take the database value for that column
Thanks

Resources