The member with identity ' ' does not exist in the metadata collection.\r\nParameter name: identity - asp.net-mvc

I simplified the code a little while trying to debug:
[HttpPost]
public ActionResult Register(User model)
{
DateTime bla = new DateTime(2012, 12, 12);
try
{
User user = new User
{
gid = 1,
cid = 1,
firstName = model.firstName,
lastName = model.lastName,
email = model.email,
username = model.username,
password = model.password,
creationDate = bla,
active = 1
};
myContext.Users.AddObject(user);
myContext.SaveChanges();
}
catch (Exception ex)
{
throw ex;
}
return View();
}
The values are transmited accordingly. Users table:
[id] [int] IDENTITY(1,1) NOT NULL,
[cid] [int] NULL,
[gid] [int] NULL,
[firstName] [nvarchar](100) NOT NULL,
[lastName] [nvarchar](100) NOT NULL,
[email] [nvarchar](max) NOT NULL,
[username] [nvarchar](100) NOT NULL,
[password] [nvarchar](100) NOT NULL,
[creationDate] [datetime] NOT NULL,
[active] [int] NOT NULL,
CONSTRAINT [PK_Users_3213E83F0AD2A005] PRIMARY KEY CLUSTERED
I deleted all the foreign keys to be sure that nothing affects it. I am qute certain that at a previous moment it was working, but now I can not figure where the issue is.
It crashes while performing the savechanges:
{"An error occurred while updating the entries. See the inner exception for details."}
{"The member with identity '' does not exist in the metadata collection.\r\nParameter name: identity"}

I had the same error being thrown when I try to insert using EF, the error was
The member with identity 'Id' does not exist in the metadata collection.\r\nParameter name: identity
It wasn't obvious at first but the exception message was very concise because my database knows the column Id int but the property created for the object on my code was int ID so coming back to named mapping, Id is not mapped to ID.
So when an object with property ID is sent to database that only know Id you will get the above error.
I hope this helps, thanks

The issue was reproducing because of a trigger that was on the users table. Removed it and the issue is not reproducing anymore.

There is probably a trigger on the table being updated and it returns output. The output is thrown away but it conflicts with EF. Such output is often used to debug triggers (and forgotten to delete later):
select 'trigger called, i am here'
or there can be missing variable:
select column
instead of
select #variable=column

I think that the best solution is in this post. I used the 3rd option and works.
Here I report the reply in the link:
The issue could be related to a "instead of insert" trigger on one of
your tables.
The EF framework is performing validation on the inserted row of data
by calling scope_identity(). However, an "instead of insert" trigger
will change the context of the insertion in such a way that the EF
system's call to scope_identity will return null.
A couple ways around this:
Use a stored procedure to insert the data ( not tested )
Remove the instead of insert trigger ( triggers can cause other problems, so some people argue not to use them) ( tested, works!)
Turn off validation in the EF framework, so: context.Configuration.ValidateOnSaveEnabled = false ( tested, works!)

I had this same error today and spent a few frustrating hours trying to figure it out.
I was using Entity Framework to insert a record with an identity column into a SQL server database table. Simple enough.
The table had a trigger on it which in turn ran a stored procedure. The stored procedure had a line in it:
select newid()
This is the line that broke Entity Framework.
For tables with identity columns, Entity Framework expects to be returned a single row with a single field that is the identity column.

it's because of trigger pass back value to EF
if you are using trigger. in my problem i must check a value by selecting from other table and using of 'select' cause error in EF, so you must replace 'select' with 'set'.
you can not use this code.
select #any= any from tablename
you should use set instead of select
set #any= (select any from tablename)

Somedays, I hate M$.
The member with identity 'ChangeID' does not exist in the metadata collection.
Parameter name: identity
I've spent two days trying to get around this.
I'm using MVC.
To get all the data I need in one fell swoop, I created a view of the table in the DB for this application, and tables in other databases. (You may update views, with some constraints.)
I do a get, and all my data is present in the record, keys, descriptions, foreign keys, etc.
I created triggers on my view, to update the portion of the view that came from the local table.
Instead of Delete worked fine.
Instead of Update worked fine.
This error kept raising it's head on Instead of Insert. I could NOT get the insert trigger to successfully insert into my table. If I ran an insert on the view, with all fields provided in the SQL Management Studio, it worked fine. I know the exact values being passed because I ran SQL Server Profiler to see the code being passed.
But when the app attempted the update, it failed with The member with identity 'ChangeID' does not exist in the metadata collection.
Clue up above, someone said, "MVC expects table key to be ID"
I renamed ChangeID as ID in my view, changed it in the App, and BAM! Now it works.
What did NOT work:
db.Configuration.ValidateOnSaveEnabled = false;
adding a select to the trigger to get scope identity
Why do I have to modify my DB or my view to satisfy some hidden M$ assumption?
None the less, after two very frustrating days, code is now working. Maybe this will save someone else some time as well.

Try this
[HttpPost]
public ActionResult Register(User model)
{
DateTime bla = new DateTime(2012, 12, 12);
try
{
model.gid = 1;
model.cid = 1;
model.creationDate = bla;
model.active = 1;
myContext.Users.AddObject(model);
myContext.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
return View();
}

I was having this issue and my fix, was that in my connection-string metadata I did not specify my model in the .msl format.
See more info here

In my case, SetName of the entity was incorrect. Shortly, this worked for me:
Use
myContext.AddObject(nameOfSetEntity, user);
Instead of:
myContext.Users.AddObject(user);
To get the whole correct name of the entity (thanks to Nix's answer)
string className = typeof(User).Name;
var container = myContext.MetadataWorkspace.GetEntityContainer(myContext.DefaultContainerName, System.Data.Metadata.Edm.DataSpace.CSpace);
string nameOfSetEntity= (from meta in container.BaseEntitySets
where meta.ElementType.Name == className
select meta.Name).First();
Context.AddObject(nameOfSetEntity, user);

Related

Can I generate migration seeds from an sql script?

I'm using Sqlserver and .NETCore to create backend for my project.
and I have so many tables with so much data.
I was wondering, is there a way to generate seeds to use in my migration from the existing db tables?
i.e : I want to generate this from the table FamilyMemberPrivileges
modelBuilder.Entity<FamilyMemberPrivileges>().HasData(
new FamilyMemberPrivileges
{
Id = 1,
Name = "full control"
},
new FamilyMemberPrivileges
{
Id = 2,
Name = "control over self"
},
new FamilyMemberPrivileges
{
Id = 3,
Name = "read-only"
}
);
I have searched everywhere for this, maybe it doesnt work like that. but no harm in asking!
also, if this is not possible, is there an easier way to do this instead of writing the seeds myself?
Thanks!
You can write a Sql Statement that returns C# code and run it in SSMS. An example will be like:
select 'new FamilyMemberPrivileges{ Id ='+ convert(varchar(10), [Id] )+ ', Name="'+ [Name] + '"},'
from dbo.FamilyMemberPrivileges
The result will look like this
-------------------------------------------------------------------------------
new FamilyMemberPrivileges{ Id =1, Name="Full Control"},
new FamilyMemberPrivileges{ Id =2, Name="Control Over Self"},
(2 rows affected)
And then copy + paste the result to your code

cannot insert data in table manually through server explorer in visual studio when code first migration is used

I wanted to insert data manually in table.
when i do so, i get this error [see image below]
how to fix this issue
please help
error Image attached
Since you tagged this migrations, and it appears you are trying to get data into your tables that mechanism is called Seeding. You can override the Seed() method like this:
protected override void Seed(MyDbContext context)
{
context.Customers.AddOrUpdate(
c => c.Name, // Use Name (or some other unique field) instead of Id
new Customer
{
Name = "Customer 1",
IsSubscribed = false,
MembershipTypeId = 1 // A value from MembershipType table
},
new Customer
{
Name = "Customer 2",
IsSubscribed = true,
MembershipTypeId = 2 // A value from MembershipType table
});
context.SaveChanges();
}
Now, when you run update-database this code will run and if the customers are not in the database, they will be added. If you delete the database they will be added next time you run migrations.
If you just want to manually insert, then you will need to provide a valid MembershipTypeId in that column (search you MembershipType table for valid values).

autogenerated keys for entities with multipart keys

I was trying to create a new object with multicolumn primary key formed by a foreign key and a self-generated field and I found this error:
Ids can not be autogenerated for entities with multipart keys.
For now, and although not the most appropriate, I will change the key but the question is:
Are you planning support multicolumn primary key autogenerated soon?
I will add the request to uservoice too.
A greeting.
Edit to explain the use case:
Hello,
True, it may not make sense to have a primary key composed by a foreign key and a self-generated field.
My idea was to build a table like this:
ParentID ChildID Data
1 1 Some Data...
1 2 Some Data...
2 1 Some Data...
2 2 Some Data...
As a first step I did a table like this:
ParentID ChildID Data
1 1 Some Data...
1 2 Some Data...
2 3 Some Data...
2 4 Some Data...
Where ChildID was a self-generated field.
So you can ignore my question.
A greeting.
I've had the same problem but I have successfully solved it without changing the Primary Key (PK).
My PK had 2 columns
ProductId (identity)
TenantId (multitenant application)
so the first problem was Breeze couldn't generate new PK when the new item was added to the EntityManager. And I have defined custom entity initialization function:
var manager = new breeze.EntityManager(breezeServiceUrl);
var store = manager.metadataStore;
function itemInitializer(item) {
if (item.ProductId() == 0) {
item.ProductId(/*Some counter value*/);
}
if (item.TenantId() == 0) {
item.TenantId(TenantId);
}
if (item.isBeingEdited === undefined) {
item.isBeingEdited = ko.observable(false);
}
};
store.registerEntityTypeCtor("ProductItem", function() {/*Leave empty to use default constructor*/}, itemInitializer);
The second problem is that Breeze couldn't update the ProductId with the real value from EntityFramework because it gets the entity by PK and the returned value had only ProductId. So you need to override the function:
var entityType = store.getEntityType("ProductItem");
var entityGroup = manager.findEntityGroup(entityType);
entityGroup._fixupKey = function (tempValue, realValue) {
var ix = this._indexMap[tempValue + ":::" + TenantId]; //Changed line
if (ix === undefined) {
throw new Error("Internal Error in key fixup - unable to locate entity");
}
var entity = this._entities[ix];
var keyPropName = entity.entityType.keyProperties[0].name;
entity.setProperty(keyPropName, realValue);
delete entity.entityAspect.hasTempKey;
delete this._indexMap[tempValue];
this._indexMap[realValue] = ix;
};
If you have any other questions about multipart keys, you can read it in the blog.
This feature is not currently on the roadmap, but I want to better understand your use case for this. As you already know, Breeze supports auto-generated keys, and Breeze supports multi-part keys, but what scenarios do you find using both at the same time to be helpful?
Thanks!
Actually having a multipart key where part of the key is autogenerated is actually pretty common. This usually occurs with legacy databases where the primary key consists of a foreign key property and a 'autogenerated' sequence number property. Usually this autogenerated key is not globally unique by itself, but only in conjunction with the foreign key property. Think of an orderDetail with a foreign key of "OrderId, SequenceNumber".
What doesn't seem to make as much sense is when the primary key consists of more than one autogenerated property.
In Breeze the autogenerated keys are intended to be globally unique. Whereas, in the multipart key mentioned above the SequenceNumber would not be globally unique ( and if it were then why not make it the primary key all by itself).
Does this make sense?

OptimisticConcurrencyException when updating child entities

NOTE: This is based on my question here but this is subtly different. I have resolved the issue on the other question, this is specifically regarding child entities.
I have a data-structure such that:
SecurityPolicy 1<---* SecurityPolicyRule
Therefore, a SecurityPolicy can have 0, one or many SecurityPolicyRules.
I am using Julie Lerman's Entity Framework book to implement some degree of concurrency checking, TDD and POCO support.
I understand that each table should have a rowversion/timestamp field, which is marked as ConcurrencyMode==Fixed.
I have decided to implement the CUD in Stored Procedures. My UPDATE Sproc is as follows:
create PROCEDURE dbo.sp_M2_Core_UpdateSecurityPolicy
#ID int,
#Name nvarchar(256),
#Comment nvarchar(max)=null,
#timestamp timestamp
AS
declare #nameExists nvarchar(256)
select #nameExists= [Name] from M2_Core_SecurityPolicy where [Name]=#Name and [ID]<>#id
if (not #nameExists is null)
begin
raiserror (N'Name is already in use: %s',
11,
1,
#Name)
end
else
begin
update M2_Core_SecurityPolicy
set [Name]=#Name,
[Comment]=#Comment
where id=#id and [timestamp]=#timestamp
IF ##ROWCOUNT>0
SELECT [Timestamp] AS newTimeStamp FROM M2_Core_SecurityPolicy WHERE id=#id
end
go
create PROCEDURE dbo.sp_M2_Core_UpdateSecurityPolicyRule
(
#id int,
#RoleName nvarchar(256),
#Rank int,
#CanReadExecute bit=null,
#CanWrite bit=null,
#CanDelete bit=null,
#CanExport bit=null,
#Timestamp timestamp
)
AS
declare #roleExists nvarchar(256)
declare #securityPolicyID int
select #roleExists= [RoleName] from vw_aspnet_Roles where [RoleName]=#RoleName
if (#roleExists is null)
begin
raiserror (N'Role is not defined: %s',
11,
1,
#roleName)
end
else
begin
select #securityPolicyID=[SecurityPolicyID] from M2_Core_SecurityPolicyRule where [id]=#id
-- move all other rules up in priority
IF (SELECT COUNT(*) FROM M2_Core_SecurityPolicyRule WHERE [ID]<>#ID AND [SecurityPolicyID]=#SecurityPolicyID AND [Rank]=#Rank) > 0
BEGIN
UPDATE M2_Core_SecurityPolicyRule
SET [Rank]=[Rank]+1
WHERE [Rank] >= #rank
AND [SecurityPolicyID]=#SecurityPolicyID
AND [ID]<>#ID
END
update M2_Core_SecurityPolicyRule
set [RoleName]=#RoleName,
[Rank]=#Rank,
[CanReadExecute]=#CanReadExecute,
[CanWrite]=#CanWrite,
[CanDelete]=#CanDelete,
[CanExport]=#CanExport
where id=#id and [timestamp]=#timestamp
IF ##ROWCOUNT>0
SELECT [Timestamp] AS newTimeStamp FROM M2_Core_SecurityPolicyRule WHERE id=#id
end
RETURN
go
I am testing this using some code that:
Creates a Security Policy
Adds a created Security Policy Rule to the Security Policy
Adds the Security Policy
Saves the updates
Adds 1 to the Rank of the Security Policy Rule
Saves the updates
The test is below:
[TestMethod()]
public void AddWithSecurityPolicyRuleChangeRankTest()
{
ICoreContext coreContext = new CoreEntities(_coreDbConnectionString);
CoreUnitOfWork coreUnitOfWork = new CoreUnitOfWork(coreContext);
SecurityPolicyRepository target = new SecurityPolicyRepository(coreUnitOfWork);
int originalCount = coreContext.SecurityPolicies.Count();
string securityPolicyName = "addwithsecuritypolicyrulechangeruletest";
int originalRank = 1;
SecurityPolicy entity = new SecurityPolicy()
{
Comment = null,
Name = securityPolicyName,
SecurityPolicyRules = new FixUpCollection<SecurityPolicyRule>()
};
entity.SecurityPolicyRules.Add(
new SecurityPolicyRule()
{
CanDelete = null,
CanExport = null,
CanReadExecute = null,
CanWrite = null,
Rank = originalRank,
RoleName = "User"
});
target.Add(entity);
coreUnitOfWork.Save();
entity.SecurityPolicyRules[0].Rank=originalRank+1;
coreUnitOfWork.Save(); // <-- exception thrown here
SecurityPolicy savedSecurityPolicy = target.GetAll().Single(q => q.Name.Equals(securityPolicyName, StringComparison.CurrentCultureIgnoreCase));
Assert.AreEqual(originalRank+1,savedSecurityPolicy.SecurityPolicyRules[0].Rank);
}
However, when I run this, it throws an exception at the highlighted line. The exception is:
System.Data.OptimisticConcurrencyException
was unhandled by user code
Message=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.
Source=System.Data.Entity
StackTrace:
at System.Data.Mapping.Update.Internal.UpdateTranslator.ValidateRowsAffected(Int64
rowsAffected, UpdateCommand source)
at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager
stateManager, IEntityAdapter adapter)
at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager
entityCache)
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions
options)
at System.Data.Objects.ObjectContext.SaveChanges()
at MIGTurbo2.Core.Data.CoreEntities.Save()
in
D:\dev\migturbo2.0\MIGTurbo2.Core\Data\Core.Context.cs:line
92
at MIGTurbo2.Repositories.CoreUnitOfWork.Save()
in
D:\dev\migturbo2.0\MIGTurbo2.Repositories\CoreUnitOfWork.cs:line
26
at MIGTurbo2.Core.Tests.IntegrationTests.SecurityPolicyRepositoryTest.AddWithSecurityPolicyRuleChangeRankTest()
in
D:\dev\migturbo2.0\MIGTurbo2.Core.Tests\IntegrationTests\SecurityPolicyRepositoryTest.cs:line
524 InnerException:
And sure enough, no data has changed. ie. The [Rank] is still 1 from the first update (therefore, the INSERT). However, running it through SQL Profiler and Ayende's EF Profiler, no calls to the database are even made to make the UPDATE. So the relevance of the timestamp/rowversion is surely ... irrelevant?
What could be causing this? I don't want to have to Refresh the DB on every Save! This ONLY happens when updating the child entity. Changing the parent SecurityPolicy works fine.
Update 1:
When running the INSERT code, the SecurityPolicyRule is created fine. This issue is specific to UPDATE and DELETE operations.
Update 2:
I've figured out that if I set the state of the entity, it does get submitted to the database. The EF is obvioulsy picking up my State property (using the mechanism explained in Julie's book) fine now. So my test code now looks like this when updating the item:
entity.SecurityPolicyRules[0].Rank=originalRank+1;;
entity.SecurityPolicyRules[0].State = IWW.Elements.State.Modified;
However, despite the call and parameters sent to the database being present and correct, it is still not working. Interestingly, as shown in the screenie below, the last line is displayed AFTER the exception. Though I'm sure that this is only down to the Entity Framework Profile "flushing" its monitors.
Is the Stored Procedure of the child entity returning correct data?

Cannot insert duplicate key

I am getting this error ...
Violation of PRIMARY KEY constraint 'PK_Members'. Cannot insert duplicate key in object 'dbo.Members'.
The statement has been terminated.
When I try to use the Membership and Role Providers in ASP.NET MVC. It happens when calling the GetUser method from inside the RoleProvider.
var member = System.Web.Security.Membership.GetUser(email) as Models.Member;
//var member = (
// from m in DataContext.Members
// where m.Email == email
// select m).Single();
var role = (
from r in DataContext.Roles
where r.Name == roleName
select r).Single();
member.Groups.Add(new Models.Group(role));
DataContext.SubmitChanges();
It looks like the problem is in the code
member.Groups.Add(new Models.Group(role));
Based on the error message returned by the sql, Read operation like GetUser won't throw this type of error.
I suspect it's because you are adding a group that exists already.
Maybe you should check for the existance of the role before trying to add it.
Hope this helps.
A good way to debug this is to use SQL profiler to determine what SQL code is being run against the database.
I would suspect you are trying to save a record somewhere that has the same primary key already in the database.
SQL Profiler = http://msdn.microsoft.com/en-us/library/ms181091.aspx
Are you sure you are not trying to enter a number into the PRIMARY KEY field that is already there? If it is auto_increment, just enter 0 and it will make the value of that field, the last number+1
Hope this helps :)
If the exception is an SqlException you might get its error number for duplicate records which is 2627. You might catch the exception and verify it and display and manage any error accordingly. I Hope this helps.
catch (SqlException ex)
{
if (ex.Number == 2627)
{
MessageBox.Show("This record exists: "+ex.Message, "Error");
}
else
{
MessageBox.Show(ex.Message, "Error")
}
}
I am a newbie at this but I am going to give this a try, sorry if it doesn't work for you.
I think that instead of using,
member.Groups.Add(new Models.Group(role));
You should use the following (if you are updating the database):
member.Groups.Entry(new Models.Group(role));
And if the above code doesn't work, try this (if you are adding to the database):
// First, search for the particular obj you want to insert
var checkModels = member.Groups.Find(new Models.Groups(roles));
// If the obj doesn't already exist, add it to the database
if(checkModels == null){
member.Groups.Add(new Models.Group(role));
}
// If the obj does exist already, then update it
else{
member.Groups.Entry(new Models.Group(role)).State = EntityState.Modified;
}

Resources