Getting a the new value of RowVersion using Entity Framework 6 - asp.net-mvc

Is is possible, to get the new value of RowVersion using the same DbContext, without reloading the entity from the database?
Scenario:
Load data into editor form
Save new values
The row in the table gets updated, new value of RowVersion is generated
However, the saved entity still holds the old value of RowVersion, so the new value can not be passed back to the client
All concurrency control articles are usually concerned only with preventing the update (e.g. see this).
However, in the example from the article, a successful update is followed by a redirect to page, where the saved entity is read again and now it has a new RowVersion value. I would like to avoid this redirect.

Thanks to grennis, I found out the source of my problems.
I defined the interface and an entity like
public interface IRowVersion
{
// Attention: this will not be "inherited" by the implementing class !!!
[Timestamp]
byte[] VersionStamp { get; set; }
}
public class Directory : IRowVersion
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
// If this attribute is missing here, then row version is used
// My initial version was without this attribute
[Timestamp]
public byte[] VersionStamp { get; set; }
}
In my problematic version, I thought that having the attribute on the interface property is enough. However, the attribute must be explicitly applied on the entity's property. Otherwise it will not be used at all (not even as the part of update SQL statement). The value was updated only because the DB updates the column value automatically and of course, at next read, I got the new value.
Not entirely related to the problem, but still worth mentioning... The following is really a killer feature of EF6
ctx.Database.Log = s => Debug.Write(s);
SQL Profiler, it was nice knowing you :-)

Related

Azure Mobile Services table to c# class mismatch: Error: Item identifiers can only be specified via the 'id' property

I've just refactored my Xamarin Android app that uses Azure Mobile Services as backend. Recently I got this really strange error.
When I try to insert a new item to the database:
_client.GetTable<T>().InsertAsync(instance)
I then get a MobileServiceInvalidOperationException that goes:
Error: Item identifiers can only be specified via the 'id' property.
It seems like AMS is not able to match the class properties with the sql table. If I change Id to id then the next issue is that it cannot match __version with my property Version.
However the strange part is that it all works if I insert or read from the table at app startup (which I did before the refactoring). And only one table has this issue.
Does anyone have a clue what it could be? I could do a workaround by reading once at startup, but that's just not satisfying.
Here is the class / table.
using Microsoft.WindowsAzure.MobileServices;
using System;
namespace Core.Models
{
public class PostAction
{
public string Id { get; set; }
public string UserId { get; set; }
public string ImageURL { get; set; }
[CreatedAt]
public DateTime CreatedAt { get; set; }
[UpdatedAt]
public DateTime UpdatedAt { get; set; }
[Version]
public string Version { get; set; }
}
}
Try to change the data type from string to int for Id property.
Azure uses strings instead of ints as PKs. I you have old data in your app it might work up to a certain point since SQLite is pretty tolerant in terms of types. BUT at some point eg. if you used foreign key relations you will have to migrate your database.

Insert values to entity framework in asp.net mvc4

In my asp.net mvc4 sample i have table in the name of Sample with three column as Name,Dept and Id.In this Id as identity and primary.I get a value for Name and Dept from user and insert that value to Sample table of entity framework.It pass value '0' to Id.And i got an error as "Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries".Please help me.
set "autoincrement" on the column and set the id as primary key in sql server ..
In EF code-first this is done by data annotations. Make sure you recreate your table (or database) after changing the scheme.
public class Sample
{
[Key]
[Required]
[Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] //auto increment id
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int Dept { get; set; }
}
You don't need to pass an integer for Id. EF will resolve this automatically. Just create the object by filling in the name and the dept. By saving the changes to the database, EF will automatically fill in the auto generated Id.

Modeling an existing database

I want to generate a model based on an existing database -- I thought it would be as simple as writing the model, adding a DbContext class, and configuring a connection string:
namespace MyProject.Models
{
public class Account
{
public int Id { get; set; }
public string Email { get; set; }
public string Name { get; set; }
}
public class AccountDBContext : DbContext
{
public DbSet<Account> Accounts { get; set; }
}
}
With a simple boilerplate controller
public ActionResult Index()
{
return View(db.Accounts.ToList());
}
The boilerplate view, which I won't post here, which lists all of the members of the db object that we return.
ANd finally, a connection string:
<add name="AccountDBContext" providerName="System.Data.SqlClient" connectionString="[server connection string]" />
Only problem is I don't see any entries being displayed. It's definitely connecting, but not retrieving or displaying the data that the particular DB contains.. am I missing something?
Edit
Ok, so first thing is first: it wasn't connecting. I had a typo in my connection string name. It was hitting the default, and subsequently displaying nothing.
What I am getting now, though, is The model backing the 'AccountDBContext' context has changed since the database was created.
Is this because my model doesn't match exactly to what the database contains?
This is the "Code First with an Existing Database" scenario.
What version of EF are you using?
In EF 4.3 when you let code first create a database for you, it inserts a Migration-History table into the new database. It’s hidden in System Tables.This is equivalent to the EdmMetadata table you got with EF 4.1 & 4.2. But when you already have the database you can use code first migrations. (http://msdn.microsoft.com/en-US/data/jj591621)
Either way you should probably check if such a table exist. If it does you can delete it and then you'll be solely responsible to correctly matching your pocos to the database.
Another quick workaround i have found is putting
Database.SetInitializer<YourContext>(null);
to your Application_Start() in Global.asax
See also this similar question: Entity Framework Code Only error: the model backing the context has changed since the database was created

Concurrency/Timestamp required for new Entity

Trying to save a new Entity with this field
[Timestamp]
public byte[] TimeStamp { get; set; }
throws the validation error Required. I am not setting any value on TimeStamp before save. Saving an existing item changes the TimeStamp in the DB as expected.
This value is set by the DB itself and as such does not need to be initialized, or am I wrong here?
EDIT:
This works i think because it is nullable
[ConcurrencyCheck]
public int? RowVersion { get; set; }
A new DB-Entry has null as value. Any change from within my app changes this and adds 1.
This was a bug and is now fixed in v 0.76.4. You should be able to use SQL Server timestamps cleanly now. ... Thanks for finding this, Sascha.

ASP.NET MVC / DDD architecture help

I am creating a Web application using ASP.NET MVC, and I'm trying to use domain-driven design. I have an architecture question.
I have a WebControl table to store keys and values for lists so they can be editable. I've incorporated this into my business model, but it is resulting in a lot of redundant code and I'm not sure it belongs there. For example, in my Request class I have a property called NeedType. Because this comes from a list, I created a NeedType class to provide the values for the radio buttons. I'm showing just one example here, but the form is going to have probably a dozen or so lists that need to come from the database.
[edit, to clarify question] What's a better way to do this? Are these list objects really part of my domain or do they exist only for the UI? If not part of the domain, then they don't belong in my Core project, so where do they go?
public class Request : DomainObject
{
public virtual int RequestId { get; set; }
public virtual DateTime SubmissionDate { get; set; }
public virtual string NeedType { get; set; }
public virtual string NeedDescription { get; set; }
// etc.
}
public class NeedType : DomainObject
{
public virtual int NeedTypeId { get; set; }
public virtual string NeedTypeCode { get; set; }
public virtual string NeedTypeName { get; set; }
public virtual int DisplayOrder { get; set; }
public virtual bool Active { get; set; }
}
public class RequestController : Controller
{
private readonly IRequestRepository repository;
public RequestController()
{
repository = new RequestRepository(new HybridSessionBuilder());
}
public RequestController(IRequestRepository repository)
{
this.repository = repository;
}
public ViewResult Index(RequestForm form)
{
ViewData.Add("NeedTypes", GetNeedTypes());
if (form == null)
{
form = new RequestForm();
form.BindTo(repository.GetById(125));
}
}
private NeedType[] GetNeedTypes()
{
INeedTypeRepository repo = new NeedTypeRepository(new HybridSessionBuilder());
return repo.GetAll();
}
}
Create a seperate viewmodel with the data you need in your view. The Model in the M of MVC is not the same as the domainmodel. MVC viewmodels are dumb DTO's without behaviour, properties only. A domain model has as much behaviour as possible. A domain model with get;set; properties only is considered an anti-pattern called "anemic domain model". There are 2 places where most people put the viewmodels: in the web layer, close to the views and controllers, or in a application service layer.
Edit:
When you only need to display a list of all needtypes in the database and one request in your view, I would indeed create one viewmodel with the request and the list of needtypes as properties. I don't think a call to multiple repositories in a controller is a smell, unless you have a larger application and you might want a seperate application service layer that returns the whole viewmodel with one method call.
I think it might also be a good idea to follow the advise of Todd Smith about value object.
When the needtypes can be added or edited by users at runtime, needtype should be an entity. When the needtypes are hardcoded and only changed with new releases of the project, needtype should be a value object and the list of needtypes could be populated by something like NeedType.GetAll() and stored in the database by adding a column to the request table instead of a seperate needtype table.
If it comes from a list, then I'm betting this is a foreign key. Don't think about your UI at all when designing your domain model. This is simply a case where NeedType is a foreign key. Replace the string NeedType with a reference to an actual NeedType object. In your database, this would be a reference to an id.
When you're building your list of NeedType choices, you simply need to pull every NeedType. Perhaps keeping it cached would be a good idea if it doesn't change much.
Your NeedType looks like a value object to me. If it's read-only data then it should be treated as a value object in a DDD architecture and are part of your domain.
A lot of people run into the "omg so much redundancy" issue when dealing with DDD since you're no longer using the old Database -> DataTable -> UI approach.

Resources