Database table:
CREATE TABLE [dbo].[EmployeeDetails]
(
[id] [int] PRIMARY KEY IDENTITY(1,1) NOT NULL,
[Name] [varchar](max) NULL,
[Emailid] [varchar](max) NULL,
[department] [varchar](max) NULL,
[Salary] [int] NULL,
[Profile] [varchar](max) NULL,
[Description] [varchar](max) NULL,
[ReferencesId] [int] NULL
)
Model class:
public class Employee
{
#region properties
public int Id { get; set; }
public string? Name { get; set; }
public string? Emailid { get; set; }
public string? department { get; set; }
public int salary { get; set; }
public string? Profile { get; set; }
public string? Description { get; set; }
#endregion
}
ClassMappper
public class EmployeeMapper : ClassMapper<Employee>
{
public EmployeeMapper()
{
Table("EmployeeDetails");
Map(x => x.Id).Key(KeyType.Identity).Column("Id").Type(System.Data.DbType.Int32);
Map(x => x.Name).Column("Name");
Map(x => x.Emailid).Column("Emailid");
Map(x => x.department).Column("department");
Map(x => x.salary).Column("Salary");
Map(x => x.Profile).Column("Profile");
Map(x => x.Description).Column("Description");
}
}
Insert code:
public int Add(T entity)
{
int count = 0;
using (var con = _dapperContext.CreateConnection())
{
int id = con.Insert(entity);
if (id > 0)
{
count++;
}
}
return count;
}
I get this error:
System.ArgumentException: 'Object of type 'System.Int64' cannot be converted to type 'System.Int32'.'
I show this exception on the page but data is inserted in database successfully. My database datatype and model class datatypes both are the same, but I still get this "Conversion Error" on the page
I need insert one new row into the database table using Dapper Extension in ASP.NET Core Razor page
enter image description here
I show this exception on the page but data is inserted in database
successfully. My database datatype and model class datatypes both are
the same, but I still get this "Conversion Error" on the page
Well, at the beginning I was thinking you are doing something silly. Out of my curiosity, I get into it and got to know issue is not within your code its Dapper-Extensions issue. I have investigate quite a long while with their document and seems its older version and currently they are not supporting it. I have gone through this official document.
Issue Reproduced:
I have have reproduced the issue which has been thrown from Dapper-Extensions method as can be seen below:
Dapper Extension Method:
Exception:
Stacktrace:
at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
at DapperExtensions.DapperImplementor.InternalInsert[T](IDbConnection connection, T entity, IDbTransaction transaction, Nullable`1 commandTimeout, IClassMapper classMap, IList`1 nonIdentityKeyProperties, IMemberMap identityColumn, IMemberMap triggerIdentityColumn, IList`1 sequenceIdentityColumn)
at DapperExtensions.DapperImplementor.Insert[T](IDbConnection connection, T entity, IDbTransaction transaction, Nullable`1 commandTimeout)
at MVCApps.Controllers.UserLogController.Add() in D:\MyComputer\MsPartnerSupport\MVCApps\Controllers\UserLogController.cs:line 1371
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
Note:
While debugging and reproduce the issue, I have tried to use data type both int in both side as well as other data type for instance, bigint but still that conversion error taken place and I found this issue is known in regards of Dapper-Extensions. Thus, one data-type works out accordingly that is GUID. I still not sure, how these Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast are Intervening here.
Solution-Work Around:
As of now, int, bigint always throws 'Object of type 'System.Int64' cannot be converted to type 'System.Int32'.' hence, the reason is not clear which coming from DapperExtensions.DapperExtensions.Insert() method.
Furthermore, to avoid above error, we can do as following:
POCO Model:
public class Employee
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Emailid { get; set; }
public string Department { get; set; }
public int Salary { get; set; }
}
Note:
Other than Guid currently not working, I am not sure the reason behind this. So if you would like to stick to your implementation, you could consider Guid.
Database Schema:
CREATE TABLE Employee(
[Id] UNIQUEIDENTIFIER PRIMARY KEY DEFAULT NEWID(),
[Name] [varchar](25) NULL,
[Emailid] [varchar](100) NULL,
[Department] [varchar](25) NULL,
[Salary] [int] NULL,
)
Asp.Net Core Controller/Repository Method:
public int Add()
{
int count = 0;
Employee employee = new Employee();
employee.Name = "Kudiya";
employee.Emailid = "email#someemail.com";
employee.Department = "Dapper";
employee.Salary = 500;
using (SqlConnection conn = new SqlConnection(_connectionString))
{
conn.Insert(employee);
Guid Id = employee.Id;
if (Id != null)
{
count++;
}
}
return count;
}
Note: Please update the code snippet based on your scenario and context.
Output:
Note: Moreover, based on the stacktrace, if someone has the exact explnation or findings, please do let me know. I wound happy to update my answer.
Related
Pulling my hair out on this one. I am executing SQL Server stored procedures using FromSqlRaw in various places of my code and all its working... except one.
This is the structure of the data returned from that stored procedure:
[site_no] [missing_date] [missing_reason] [area_no]
I have a class for this data:
public class MissingData
{
public short site_no { get; set; }
public DateTime missing_date { get; set; } = DateTime.MinValue;
public string missing_reason { get; set; } = string.Empty;
public int area_no { get; set; }
}
In my context I have this.
public DbSet<MissingData> MissingData { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MissingData>().HasNoKey();
}
and the code to execute it all is this
var dbSet = connection.Set<MissingData>();
var items = dbSet.FromSqlRaw(sql).ToList(); // SQL is string with query
I get an exception on the last line of code:
An item with the same key has already been added. Key: site_no
Any ideas?
UPDATE:
In regards to primary keys of the table. Both site_no and area_no are primary keys of their respected tables. The SQL does a join from 2 tables. So I did try this
modelBuilder.Entity<MissingData>().HasKey(x => new {x.site_no, x.area_no});
This made no difference. I have even edited the stored procedure to create a temporary table with no primary keys. Fill the table and then return this table. Still the same error.
Exception Stack trace, no inner exceptions
at System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException[T](T key)
at System.Collections.Generic.Dictionary2.TryInsert(TKey key, TValue value, InsertionBehavior behavior) at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable1 source, Func2 keySelector, Func2 elementSelector, IEqualityComparer1 comparer) at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlQueryingEnumerable1.BuildIndexMap(IReadOnlyList1 columnNames, DbDataReader dataReader) at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlQueryingEnumerable1.Enumerator.InitializeReader(DbContext _, Boolean result)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func3 operation, Func3 verifySucceeded)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlQueryingEnumerable1.Enumerator.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)
An example of data returned
[site_no] [missing_date] [missing_reason] [area_no]
[56] [2021-06-10 00:00:00] [FTP From Site Failed] [53]
[56] [2021-06-10 00:00:00] [FTP From Site Failed] [58]
[56] [2021-06-10 00:00:00] [FTP From Site Failed] [3]
[56] [2021-06-10 00:00:00] [FTP From Site Failed] [55]
[9] [2021-06-10 00:00:00] [FTP From Site Failed] [11]
From the stack trace, I think the error is throw by EF Core from :
GitHub source :
public static int[] BuildIndexMap(IReadOnlyList<string> columnNames, DbDataReader dataReader)
{
var readerColumns = Enumerable.Range(0, dataReader.FieldCount)
.ToDictionary(dataReader.GetName, i => i, StringComparer.OrdinalIgnoreCase);
...
The error isn't about a duplicate row, but a duplicate column name. Maybe you stored procedure return two (or more) column with the name "site_no".
I have a setup as follows.
Supermaster has a collection of Master.
Master having FK reference to Reference PK Id
Reference table has readonly reference data.
In ef code when i load records from Supermaster table i add reference to each Master based on some condition.
on submission of Supermaster i expect Supermaster to be saved with all Master with reference to Reference.
But on dbContext.SaveChanges() EF tries to insert record to Reference and fails with PK constrain.
What i have tried till now
I have tried creating one to one relationship with foreign Key using Fluent API.
I have tried Detaching Entity before saving the context
_context.Entry(programmingRecord.ProgrammingRecordParameters.Select(x=>x.ValidationRule)).State = EntityState.Detached;
.
Here is code.
Entity
Public class Supermaster
{
public virtual ICollection<Master> ProgrammingRecordParameters { get; set; }
}
public class Reference
{
public int Id { get; set; }
public string Description { get; set; }
}
public class Master
{
public int Id { get; set; }
public string DataGroup { get; set; }
[ForeignKey("ValidationRuleId")]
public Reference ValidationRule { get; set; }
public int? ValidationRuleId { get; set; }
}
API
private void AddParameter(
Supermaster rec,
Master programmableParameter)
{
var param = new Master
{
DataGroup = programmableParameter.DataGroup,
ValidationRule = _context.References.FirstOrDefault(x=>x.Description==programmableParameter.DataGroup
};
rec.ProgrammingRecordParameters.Add(param);
}
public IActionResult PostProgrammingRecord([FromBody] Master programmingRecord)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var repo = new ProgrammingRepository(_context);
_context.ProgrammingRecords.Add(programmingRecord);
_context.SaveChanges();
}
Following is the Error stack
HResult=0x80131500
Message=An error occurred while updating the entries. See the inner exception for details.
Source=Microsoft.EntityFrameworkCore.Relational
StackTrace:
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(DbContext _, ValueTuple`2 parameters)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IReadOnlyList`1 entries)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList`1 entriesToSave)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
at RadioTMS.Web.Controllers.API.ProgrammingController.PostProgrammingRecord(ProgrammingRecord programmingRecord) in D:\TMS_Git_Repo\radio-tms\RadioTMS.Web\Controllers\API\ProgrammingController.cs:line 181
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeActionMethodAsync>d__12.MoveNext()
Inner Exception 1:
SqlException: Cannot insert explicit value for identity column in table 'ValidationRules' when IDENTITY_INSERT is set to OFF.
EF is trying to insert record in reference table because entity context does not have reference data loaded.You should get record of reference loaded in context before calling save changes.
We are using Entity Framework 5 to create a new Answer record in our SQL Server 2012 database.
Here's the Answer Class:
public class Answer
{
public int? AnswerId { get; set; }
public string Text { get; set; }
}
The SQL:
CREATE TABLE Answer (
[AnswerId] INT IDENTITY (1, 1) NOT NULL,
...
...
CONSTRAINT [PK_Answer] PRIMARY KEY CLUSTERED ([AnswerId] ASC)
Here is the EF Mapping:
public class AnswerMap : EntityTypeConfiguration<Answer>
{
public AnswerMap()
{
// Primary Key
this.HasKey(t => t.AnswerId);
// Identity
this.Property(t => t.AnswerId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
However when a new Answer is inserted with a null in the AnswerId we still get the following:
The key field 'AnswerId' cannot have a value of null.
A non-null value is required for the key fields defined on type 'Answer'.
System.InvalidOperationException was unhandled by user code
HResult=-2146233079
Message=The key field 'AnswerId' cannot have a value of null. A non-null value is required for the key fields defined on type 'Answer'.
Source=System.Data.Entity
StackTrace:
at System.Data.Objects.ObjectStateManager.CreateEntityKey(EntitySet entitySet, Object entity)
at System.Data.Objects.ObjectContext.AttachSingleObject(IEntityWrapper wrappedEntity, EntitySet entitySet, String argumentName)
at System.Data.Objects.DataClasses.RelatedEnd.AddEntityToObjectStateManager(IEntityWrapper wrappedEntity, Boolean doAttach)
at System.Data.Objects.DataClasses.RelatedEnd.AddGraphToObjectStateManager(IEntityWrapper wrappedEntity, Boolean relationshipAlreadyExists, Boolean addRelationshipAsUnchanged, Boolean doAttach)
at System.Data.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)
....
So how can I add my POCO class. The only thing I can do is set AnswerId to null as it's a database generated number. But then when I do that EF complains it's null even though I specified it's an identity column to EF.
Change your Answer class to be like this:
public class Answer
{
public int AnswerId { get; set; }
public string Text { get; set; }
}
The primary key value will be automatically set by Entity Framework after the database insert.
Do not modify the AnswerId yourself, just leave it be. It will be zero for not yet inserted objects.
My task at hand is to extract DTOs directly from the DB. As ORM I use NHibernate with LINQ as a means of querying. Below are my domain classes and a DTO class which I use to return data to the client side (classes are reduced to contain only a few properties to demonstrate the point).
public class DocLanguage
{
public Guid Id { get; set; }
public string Name { get; set; }
public string PublicCode { get; set; }
}
public class Document
{
public Guid Id { get; set; }
}
public class OutgoingDocument: Document
{
public DocLanguage DocLanguage { get; set; }
}
public class OutgoingDocumentDto
{
public Guid Id { get; set; }
public Guid DocLanguageId { get; set; }
public string DocLanguageName { get; set; }
}
Here is a query I use to load DTOs from the DB.
IQueryable<OutgoingDocument> documents = GetQueryable();
var query = from doc in documents
select new OutgoingDocumentDto
{
Id = doc.Id,
DocLanguageId = doc.DocLanguage.Id,
DocLanguageName = doc.DocLanguage.Name
}
var documentList = query.ToList();
It produces the following SQL.
exec sp_executesql N'select
outgoingdo0_.documentId as col_0_0_,
doclanguag1_.Id as col_1_0_,
doclanguag1_.name as col_2_0_
from OutgoingDocuments outgoingdo0_
inner join Documents outgoingdo0_1_
on outgoingdo0_.documentId=outgoingdo0_1_.Id
left outer join DicDocLanguages doclanguag1_
on outgoingdo0_1_.docLanguageId=doclanguag1_.Id'
It works great until there is no NULL value in docLanguageId field (which is not mandatory). In another case it throws an exception:
NHibernate.Exceptions.GenericADOException was unhandled by user code
Message=Could not execute query[SQL: SQL not available]
Source=NHibernate
SqlString=SQL not available
StackTrace:
at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs:line 653
at NHibernate.Impl.AbstractSessionImpl.List(IQueryExpression queryExpression, QueryParameters parameters) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\AbstractSessionImpl.cs:line 92
at NHibernate.Impl.ExpressionQueryImpl.List() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\ExpressionQueryImpl.cs:line 61
at NHibernate.Linq.DefaultQueryProvider.ExecuteQuery(NhLinqExpression nhLinqExpression, IQuery query, NhLinqExpression nhQuery) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\DefaultQueryProvider.cs:line 103
at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\DefaultQueryProvider.cs:line 35
at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\DefaultQueryProvider.cs:line 40
at Remotion.Linq.QueryableBase`1.GetEnumerator() in :line 0
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
InnerException: System.Reflection.TargetInvocationException
HResult=-2146232828
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Delegate.DynamicInvokeImpl(Object[] args)
at System.Delegate.DynamicInvoke(Object[] args)
at NHibernate.Linq.ResultTransformer.TransformTuple(Object[] tuple, String[] aliases) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\ResultTransformer.cs:line 25
at NHibernate.Hql.HolderInstantiator.Instantiate(Object[] row) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Hql\HolderInstantiator.cs:line 80
at NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.GetResultList(IList results, IResultTransformer resultTransformer) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Hql\Ast\ANTLR\Loader\QueryLoader.cs:line 302
at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Loader\Loader.cs:line 1497
at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Loader\Loader.cs:line 1491
at NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.List(ISessionImplementor session, QueryParameters queryParameters) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Hql\Ast\ANTLR\Loader\QueryLoader.cs:line 288
at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Hql\Ast\ANTLR\QueryTranslatorImpl.cs:line 112
at NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Engine\Query\HQLQueryPlan.cs:line 105
at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Impl\SessionImpl.cs:line 643
InnerException: System.NullReferenceException
HResult=-2147467261
Message=Object reference not set to an instance of an object.
Source=Anonymously Hosted DynamicMethods Assembly
StackTrace:
at lambda_method(Closure , Object[] )
InnerException:
I've tried to explicitly check for nullity and provide default values to the DTO properties with this code:
var query = from doc in documents
select new OutgoingDocumentDto
{
Id = doc.Id,
DocLanguageId = doc.DocLanguage == null ?
Guid.Empty :
doc.DocLanguage.Id,
DocLanguageName = doc.DocLanguage == null ?
Guid.Empty :
doc.DocLanguage.Name
}
It results in this SQL.
exec sp_executesql N'select
outgoingdo0_.documentId as col_0_0_,
doclanguag1_.Id as col_1_0_,
doclanguag1_.Id as col_2_0_,
doclanguag1_.Id as col_3_0_,
doclanguag1_.name as col_4_0_,
doclanguag1_.Id as Id40_0_,
doclanguag1_.Id as Id40_1_,
doclanguag1_.name as nameRU40_0_,
doclanguag1_.publicCode as publicCode40_0_,
doclanguag1_.name as nameRU40_1_,
doclanguag1_.publicCode as publicCode40_1_
from OutgoingDocuments
outgoingdo0_ inner join Documents outgoingdo0_1_
on outgoingdo0_.documentId=outgoingdo0_1_.Id
left outer join DicDocLanguages doclanguag1_
on outgoingdo0_1_.docLanguageId=doclanguag1_.Id'
It seems that NHibernate LINQ provider bluntly converts all member access expressions in the LINQ query into SQL query producing duplicate field selects. In fact, it works, and maybe the optimizer makes this query process as fast as the previous one. But it is ugly and is getting uglier as more properties are involved.
I think this task is a common one and I'd like to know if there exists the right way of providing properties in the select clause with default values.
This probably isn't the greatest solution, but I found a blog post that shows you how to get NHibernate to recognize and translate custom extension methods used in your Linq queries, and the example specifically deals with the "coalesce" operation. The solution is to create a Coalesce() extension method, then "register" it with NHibernate by specifying a custom HQL generator for the method, then using a custom registry generator specified in the default configuration to add them to NHibernate's "knowledge base" for HQL generation.
You could theoretically do this for any extension method you have that would convert to valid SQL for your target schema; you might even use this to make NHibernate call custom SQL functions you've put in your database (but I digress).
You can solve this problem on DTO level.
You can bind your DB object to internal nullable field and use it as a backing field for your public property, where you'll place default value logic. Like so:
internal virtual DocLanguage docLanguage {get;set;}
public int DocLanguageName
{
get{ return docLanguage == null ? Guid.Empty : docLanguage.Name; }
}
I've googled this and don't get any answers for my particular circumstance.
Im using Entity Framework in a suposedly simple way. I'm trying to add a record to the Memberproduct table. However I'm getting an exception that doesn't make sense.
Any ideas what's wrong here?
MemberProduct Class:
public class MemberProduct :ISaleable
{
public void ProcessSale()
{
throw new NotImplementedException();
}
private int id { get; set; }
private string productName { get; set; }
private decimal price { get; set; }
private TaxClass taxClass { get; set; }
private int quantity { get; set; }
private Member memberAssociation { get; set; }
public TaxClass TaxClass
{
get
{
return this.taxClass;
}
set
{
this.taxClass = value;
}
}
public int Quantity
{
get
{
return this.quantity;
}
set
{
this.quantity = value;
}
}
public string ProductName
{
get
{
return this.productName;
}
set
{
this.productName = value;
}
}
public decimal Price
{
get
{
return this.price;
}
set
{
this.price = value;
}
}
public Member MemberAssociation
{
get
{
return this.memberAssociation;
}
set
{
this.memberAssociation = value;
}
}
public int ID
{
get
{
return this.id;
}
set
{
this.id = value;
}
}
}
Stack Trace:
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
at System.Data.Entity.ModelConfiguration.Conventions.IdKeyDiscoveryConvention.IdKeyDiscoveryConventionImpl.MatchKeyProperty(EdmEntityType entityType, IEnumerable`1 primitiveProperties)
at System.Data.Entity.ModelConfiguration.Conventions.KeyDiscoveryConvention.System.Data.Entity.ModelConfiguration.Conventions.IEdmConvention<System.Data.Edm.EdmEntityType>.Apply(EdmEntityType entityType, EdmModel model)
at System.Data.Entity.ModelConfiguration.Conventions.IdKeyDiscoveryConvention.System.Data.Entity.ModelConfiguration.Conventions.IEdmConvention<System.Data.Edm.EdmEntityType>.Apply(EdmEntityType entityType, EdmModel model)
at System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.EdmConventionDispatcher.Dispatch[TEdmDataModelItem](TEdmDataModelItem item)
at System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.EdmConventionDispatcher.VisitEdmEntityType(EdmEntityType item)
at System.Data.Edm.Internal.DataModelItemVisitor.VisitCollection[T](IEnumerable`1 collection, Action`1 visitMethod)
at System.Data.Edm.Internal.EdmModelVisitor.VisitEntityTypes(EdmNamespace edmNamespace, IEnumerable`1 entityTypes)
at System.Data.Edm.Internal.EdmModelVisitor.VisitEdmNamespace(EdmNamespace item)
at System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.EdmConventionDispatcher.VisitEdmNamespace(EdmNamespace item)
at System.Data.Edm.Internal.DataModelItemVisitor.VisitCollection[T](IEnumerable`1 collection, Action`1 visitMethod)
at System.Data.Edm.Internal.EdmModelVisitor.VisitNamespaces(EdmModel model, IEnumerable`1 namespaces)
at System.Data.Edm.Internal.EdmModelVisitor.VisitEdmModel(EdmModel item)
at System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.EdmConventionDispatcher.VisitEdmModel(EdmModel item)
at System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.EdmConventionDispatcher.Dispatch()
at System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.ApplyModel(EdmModel model)
at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.Initialize()
at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
at System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext()
at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
at System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)
at System.Data.Entity.DbSet`1.Add(TEntity entity)
at Nautix_EPOS.Controllers.HomeController.Index() in C:\sites\EPOS\Nautix EPOS\Nautix EPOS\Controllers\HomeController.cs:line 19
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
I could repro your issue. Your MemberProduct has two Id properties with different casing:
public class MemberProduct
{
public int Id { get; set; }
public int ID { get; set; }
}
EF code first uses conventions during the mapping. One of the convention is that it treats properties named Id or TypenameId as primary keys (if you don't use the Key attribute or custom mapping) and because it does the property name comparison case insensitively it throws the exception.
Remove one of properties and it should work.
In case it is of any use to anybody:
I received this error when populating a model using EF from a stored procedure. The stored procedure returned multiple columns, two of which had the same alias/name.
I suspect EF is getting confused by the two ID properties.
Change your private properties to fields; that should fix it.
I got this sequence error when setting Entity state info incorrectly when initially seeding. Just make sure you're setting the state of object graphs correctly. My issue was with seeding data (not during the actual application run)...here's my answer anyway if it will help anyone if they're getting a sequence error (like "Sequence contains more than one matching element") when running the update-database command for migrations. While you're getting this error outside the seed method, I think your answer might lay in the Entity states for object graphs being set correctly.
Entity Framework Code First AddOrUpdate method insert Duplicate values
To get help with setting Entity object graphs correctly, see the following blog post which is the best I've found on correctly setting object state:
http://blog.longle.net/2013/05/11/genericizing-the-unit-of-work-pattern-repository-pattern-with-entity-framework-in-mvc/