OrmLite Inserting 0 and instead of auto-incrementing primary key - c#

I am trying to create a generic Insert<T> for our objects. I am new to OrmLite so I am still reading up on it. The objects that are used do not use an Id property they have a more detailed name.
As an example this a basic POCO:
public class Customer
{
public int CustomerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
...etc.
}
So the primary key is CustomerId and through some more reading I found that OrmLite likes to use the property Id for the primary keys. As we have a convention not to use just the name Id for the FK I cannot switch. However reading further it seemed like I could decorate the property with an attribute or two and get it to work.
This is what I am working with:
public class Customer
{
[AutoIncrement]
[Alias("CustomerId")]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
...
}
I get a SqlException stating the following:
Additional information: Cannot insert the value NULL into column 'CustomerId',
table 'XXX.dbo.Customer'; column does not allow nulls. INSERT fails
I did some more reading and thought I could fix the issue by inheriting from an interface.
public class Customer : IHasId<int>
{
[AutoIncrement]
[Alias("CustomerId")]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
...
}
I have played with using the PrimaryKey attribute and I still get the same result.
Has anyone had an issue like this? If you did how did you solve it? I am having a hard time finding some more information on the matter.
I can get rid of the attributes and name the property back to CustomerId so it matches the db table and it will insert into the table but it will always put in 0 as the key, which makes sense just because it is the default value for the int but does not help me when it has to be an autoincrementing primary key. As a side note I am using ServiceStack.OrmLite.SqlServer.3.9.71 and SQL Server 2008
UPDATE 1
So I went through the documentation again today for 3.9 version of ServiceStack.OrmLite and read through their description on what I should do when I don't have POCOs with an 'Id' property for the Primary Key. It is as follows:
... by convention OrmLite expects it to be Id although you can use [Alais("DbFieldName")] attribute to map it to a column with a different name or use the [PrimaryKey] attribute to tell OrmLite to use a different property for the primary key.
I used both of the examples and it does in fact insert my data to the SQLDatabase. However, it is still inserting 0 for the CustomerId primary key.
If I use the AutoIncrement attribute it throws a SqlException:
An exception of type 'System.Data.SqlClient.SqlException' occured in System.Data.dll but was not handled by user code. Additional Information: Cannot insert the value NULL into column 'CustomerId', table 'dbo.Customer'; column does not allow nulls. INSERT fails.
Has anyone run into this issue? I keep running into roadblocks.

i experimented the same issue. Your following code was already good.
public class Customer
{
[AutoIncrement]
[Alias("CustomerId")]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
...
}
The problem don't come from ORMLITE but from your database. Indeed, the column "CustomerId" which is i think the primary key for your table have his property "Identity" set to "False". You must set it to "True" or "Yes" and also set "Identity Increment" and "Identity Seed" to 1.

In v4.0.40, servicestack retrieves the primary key column by naming convention ("column_name" == OrmLiteConfig.IdField) as shown by the following code from OrmLiteConfigExtensions.cs:
internal static bool CheckForIdField(IEnumerable<PropertyInfo> objProperties)
{
// Not using Linq.Where() and manually iterating through objProperties just to avoid dependencies on System.Xml??
foreach (var objProperty in objProperties)
{
if (objProperty.Name != OrmLiteConfig.IdField) continue;
return true;
}
return false;
}
Therefore, using [AutoIncrement] with [Alias] should not work.

Related

Why does the entity type '' require a primary key to be defined?

I am getting this error
System.InvalidOperationException: The entity type 'MyType' requires a primary key to be defined
Trying to use DbContext, DbSet etc.
I don't think MyType does need a primary key though?
Why am I being told to give it a primary key...
I have created some models that look like
public ContainerType
{
public string Id { get; set; }
public int SomeData { get; set; }
public MyType Foo { get; set; }
public MyType Bar { get; set; }
}
public MyType
{
public string SomeProperty { get; set; }
public List<OtherType> OtherTypes { get; set; }
}
and I try to create a DbSet<ContainerType> Items, but whenever I do Items.Count() I am getting that InvalidOperationException.
Why?
By definition, an "entity" is an object that has an identifier, in contrast to a "value object", where the identity of is the sum total of all its data. For example, you could have a class like:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
However, multiple people could have the same name, so the mere values of FirstName and LastName is not enough to uniquely identify a person. You need an explicit identifier:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Now, you can distinguish between two different people with the same name.
There's no coincidence that EF is Entity Framework. It's literally a framework for working with entities, i.e. objects with identifiers. That's your PK, and it is required for all entities, or else they would not in fact be entities.
If you truly feel you don't need PKs (though I would consider that assumption suspect), then EF is not the right solution for you. You might instead want to use IDistributedCache, Session, or a NoSQL store. Either of those will allow you work with any form of data you like (though you will need to serialize to/from JSON). However, you'll likely find that you'll still need ids of some sort or another.
I don't think MyType does need a primary key though?
You need a Key attributed (assuming you're using DataAnnotations) property on each class that part of your EF models. This is required to set up the foreign key relationships in the underlying relational database.
whenever I do Items.Count() I am getting that InvalidOperationException
Do you only get this error on .Count() or do all of your operations on this DbSet throw the same exception due to an invalid model?

Entity Framework - Unique constraint on a string column

I'm a beginner with EF (6.2) and I'm trying to generate a database using the code first approach.
Some of my entities have a string property which should be unique, like the name of a user or the title of an article.
In order to ensure unicity, I've added an index which specifies that the column should be unique :
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Blog.Models
{
public class User
{
[Key, Index, Required]
public int Id { get; set; }
[Index(IsUnique = true), Required]
public string Name { get; set; }
[Required]
public string Password { get; set; }
public ICollection<Comment> Comments { get; set; }
}
}
However it complains because I'm trying to add an index on a string type column, while it accepts using an index on an integer column, such as the row ID.
I could use the Key attribute, but I'm already using it to define a primary key and I don't want EF to beleive that I want the name to be a component of a composite primary key nor to consider it as the actual primary key.
So my question is : Why can't I add an index on a column of string type and how can I ensure the unicity (uniqueness ?) of a given column ? Thank you.
As written in the Tutorial from MSDN, Indexes are possible on strings as they state in the following example code
public class User
{
public int UserId { get; set; }
[Index(IsUnique = true)]
[StringLength(200)]
public string Username { get; set; }
public string DisplayName { get; set; }
}
but when it comes to Multiple-Column Indexes, they mention you need to write the order.
Probably there's a conflict arising because you use Index without any name on Id, and also an Index without any name on Name. Try defining a name for the Index of the Name. I am not sure if this works, but it's worth a try.
More info can be found here at the MSDN website.

[DatabaseGenerated(DatabaseGeneratedOption.Identity)]

I probably have spent 4 hours now and tried
Code First approach and
Database first approach
db.MoveJobs.Add(moveJob);
db.SaveChanges();
When a row is inserted it gives me
Cannot insert the value NULL into column 'id', table 'aspnet-AccountVerification.Web3.dbo.MoveJobs'; column does not allow nulls. INSERT fails.
The statement has been terminated.
public class MoveJob
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public string CountryCode { get; set; }
public string PhoneNumber { get; set; }
}
Basically I need to generate incrementally a key for every itself for a new row. No Stack overflow / Forums / or something has helped.
I strangely worked yesterday though. I cant get where i went wrong
You don't need use [DatabaseGenerated(DatabaseGeneratedOption.Identity)].
The property id by default is key and identity. First remove this attribute and drop your database, after do this add a new migration.

How to specify index column in Entitiy Framework Designer

I am currently working on my first project based on Entity Framework 6 with VS2012 using a SQL Server Compact database (model first).
Currently I am wondering how to declare an Entity column to be indexed (not unique values) in the database without being the primary key.
Thank you for any hints.
You can't specify an index through the designer. This can only be specified in the database, if you do Database-First, or through the model, if you do Code First. My preference is Database First, but your mileage may vary.
You can use the Index attribute to create Index on a particular column in the database as shown below:
class Student
{
public Student()
{
}
public int Student_ID { get; set; }
public string StudentName { get; set; }
[Index]
public int RegistrationNumber { get; set; }
}
You can also specify it to be clustered with IsClustered = true and a unique index by specifying IsUnique=true.
[Index( "INDEX_REGNUM", IsClustered=true, IsUnique=true )]
public int RegistrationNumber { get; set; }
See https://msdn.microsoft.com/en-us/data/jj591583.aspx for details like unique indexes and multicolumn indexes.

NHibernate tries to create indexes for a view

I'm writing a C# application that uses NHibernate to access the database. One of my data sources is a view (not a table) named content_profile. I have created the following sample class using NHibernate Attributes:
[Class(Table = "content_profile")]
public class ContentProfile
{
[Id(0, TypeType = typeof(int), Name = #"Id"), Generator(2, Class = #"identity"), Column(1, Name = #"Id")]
public virtual int Id { get; set; }
[NotEmpty]
[MinLength(1)]
public virtual string Name { get; set; }
[Property]
public virtual DateTime? CreationDate { get; set; }
[ManyToOne(Lazy = Laziness.False, Column = #"author_id")]
public virtual User Owner { get; set; }
}
When trying to update schema I get the following error:
NHibernate.Tool.hbm2ddl.SchemaUpdate [(null)] - Unsuccessful: alter table public.content_profile add constraint FK280FFEFD6A68A1F9 foreign key (author_id) references public.users
Npgsql.NpgsqlException:
"content_profile" - is not a table
How do I tell NHibernate that it is indeed a view, not a table, and indexes must not be created on schema update?
You can specify that there should not be done any action on the schema of a certain class map by adding SchemaAction.None, never really used attributes because it lacks features but it should have something like [Class(SchemaAction="None")]

Categories

Resources