Syntax error near AutoIncrement with SQLite Database creation - primary-key

It's me again, the guy working with SQLite-net. I had my code working when I did not have AutoIncrement on my Primary Keys of the tables. I wanted to AutoIncrement the keys so I reconstructed the Tables like this:
using SQLite;
namespace VehicleTracks.Models
{
public class vehicles
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string VehID { get; set; }
public string VehYear { get; set; }
public string VehMake { get; set; }
public string VehModel { get; set; }
public string VehColor { get; set; }
public string EngineID { get; set; }
public System.DateTime PurchaseDate { get; set; }
public string SellerName { get; set; }
public string SellerStreet { get; set; }
public string SellerCityStateZip { get; set; }
public string VehOptions { get; set; }
public string OdomInitial { get; set; }
public string VehBodyStyle { get; set; }
public float PurchaseCost { get; set; }
public byte[] VehPhoto { get; set; }
public string VehType { get; set; }
public string Sold { get; set; }
}
}
Now when an attempt is made to create the Tables, I get "Syntax Error near AutoIncrement". I tried leaving off AutoIncrement and it does not appear to increment the ID without it.
I'm probably missing something stupid.

Nothing stupid about your code; matches the code samples on https://github.com/praeclarum/sqlite-net alright. But apparently the code samples are wrong, considering this similar problem:
Android table creation Failure (near "autoincrement": syntax error)?
The problem was solved by removing AutoIncrement. Or to quote http://www.sqlite.org/faq.html#q1 :
Short answer: A column declared INTEGER PRIMARY KEY will autoincrement.
(Please double-check whether column ID actually has type INTEGER PRIMARY KEY once the table has been created.)
Longer answer: If you declare a column of a table to be INTEGER PRIMARY KEY, then whenever you insert a NULL into that column of the table, the NULL is automatically converted into an integer which is one greater than the largest value of that column over all other rows in the table, or 1 if the table is empty.
Make sure your INSERT statements do not contain an explicit value (other than NULL) for column ID, otherwise the column will not auto-increment. If that is not possible in SQLite-net (you may need a debugger here), then that may well be a bug. Though it would be surprising that nobody else has ever ran into this.
Maybe you need to make property ID nullable (i.e. use type int?; yes, with the question mark). Mind you, I'm only guessing here; you may need to experiment a bit.

sqlite> CREATE TABLE app (a INTEGER PRIMARY KEY NOT NULL, B VARCHAR);
sqlite> insert into app (b) values ('');
sqlite> insert into app (b) values ('a');
sqlite>
sqlite> insert into app (b) values ('b');
sqlite> insert into app (b) values ('c');
sqlite> insert into app (b) values ('d');
sqlite> select * from app;
1|
2|a
3|b
4|c
5|d
sqlite> exit;
NOTE: IN SQLite AUTOINCREMENT keyword is recommended not to be used. You need to use INTEGER PRIMARY KEY NOT NULL. It will automatically insert the incremented value for this attribute.

I´m new to sqlite-net ( https://github.com/praeclarum/sqlite-net ) and was having issues with an autoincrement PK.
Although I´ve created the table with INTEGER PRIMARY KEY or INTEGER PRIMARY KEY AUTOINCREMENT I got an exception on inserts because the PK was set in 0 in the first row and then I got exception because it tried to insert the same value, so the autoincrement was not working. What I have done is edit the DataAccess.cs and in the table class I´ve replaced the [PrimaryKey] public Int64 id { get; set; } for [PrimaryKey] [AutoIncrement] public Int32 id { get; set; }. I don´t know why it uses bigint (Int64) instead of Int32 as I´ve specified INTEGER in table creation, but now it´s working OK. I can add a new item through LINQ and the autoincrement id (the primary key of the table) increments automatically in each row.

Related

EF CORE CODE FIRST PRIMARY KEY COMPOSITE KEY PRIMARY KEY

I would like to know if someone knows how to make a table with a primary key composed of two columns, where the first column is sent by me, and the second is generated from the first
public class Person
{
public int idPerson { get; set; }
public string name { get; set; }
}
public class PersonAdress
{
public int idPerson { get; set; }
public int DireccionId { get; set; }
public string reference { get; set; }
}
I am looking for the incremental of the second column to be if the first column changes
how to make a table with a primary key composed of two columns
You can add the following code by fluent api in dbContext's OnModelCreating method :
modelBuilder.Entity<PersonAdress>().HasKey(sc => new { sc.idPerson , sc.DireccionId });
You can also have a reference for this.

Entity Framework - not using linked table id in insert query

I have 2 tables, Foo and Bar, Foo has a link to a Bar record
public class Foo
{
public int Id { get; set; }
public Bar SomeBar{ get; set; }
}
public class Bar
{
public int? Id { get; set; }
...
}
the SQL table (with the FK constraint between the two tables):
CREATE TABLE [dbo].[Foo] (
[Id] INT IDENTITY (1, 1) NOT NULL PRIMARY KEY,
[SomeBarId] INT NOT NULL,
CONSTRAINT [FK_Foo_Bar] FOREIGN KEY ([SomeBarId]) REFERENCES [Bar]([Id]),
);
when I save the table, Entity does not use SomeBarId in the query, producing an error, while I have set a FK constraint between the two tables
Cannot insert the value NULL into column 'SomeBarId ', table 'dbo.foo'; column does not allow nulls. INSERT fails.
how do I tell entity to use the field SomeBarId when doing the insert ?
var someBar = await _context.Bars.FindAsync(1); // fetch a Bar record
foo.SomeBar = someBar; // linking the objects
_context.Foo.Add(foo);
await _context.SaveChangesAsync();
I expect EF to get someBar.Id and use it in the query when inserting Foo in DB
thanks for the time you'll spend helping me on this
Try adding ForeignKey attribute in class Foo and remove the nullable Id in Bar
public class Foo
{
[ForeignKey("Bar")]
public int Id { get; set; }
public Bar SomeBar{ get; set; }
}
public class Bar
{
public int Id { get; set; }
...
}

Auto generate GUID in mvc5 that uses EF

I have an mvc5 application that is connected to a EF database. Some fields in this database are meant to be autogenerated as declared in SQL, but when used in MVC and upon inserting records, the GUID only contains the value of 0 for all records. How can I resolve this? Any help will be appreciated. Thanks.
Model class:
public partial class Store
{
public int StoreID { get; set; }
public int CustomerID { get; set; }
public string StoreName { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public System.Guid StoreUID { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int StoreNumber { get; set; }
public string StoreLogo { get; set; }
public string StoreLogoPath { get; set; }
public string StoreAddress { get; set; }
public string StoreCity { get; set; }
public string StoreRegion { get; set; }
public string StoreCountry { get; set; }
public virtual Customer Customer { get; set; }
}
Both StoreUID and StoreNumber supposed to be autogenerated fields. Below is an example how its supposed to be when a new store is inserted, however currently, storeNumber and StoreUID both just return 0.
You need to add defaults to your database table to generate the fields.
ALTER TABLE [dbo].[Store] ADD DEFAULT (newid()) FOR [StoreUID]
ALTER TABLE [dbo].[Store] ADD DEFAULT (myfuncthatreturnsanint()) FOR [StoreNumber]
This isn't really an Entity Framework feature. EF needs to be aware of these column types to generate the appropriate SQL. What you require is something that's actually achieved from the database. For Model First, I got the auto generated int Id functionality by modifying the T4 template that ships with EF to write the appropriate SQL, but it really is database functionality. StoreNumber is a different case since SQL server only allows one identity column.
For your database, your StoreUID column specification should be:
StoreUID uniqueidentifier not null DEFAULT newid()
You don't specify if you're dealing with model first or code first, or if you're building something new, so you may have to modify your existing table for this.
EDIT
If you're using model first, ensure that in your model the Store Generated Column is set to Identity for the StoreUID value to be server generated. If not, and you're not worried about who/what creates the GUID, then create a default constructor for Store, if you don't already have one. Then in there add StoreUID = Guid.NewGuid();.
For StoreNumber, SQL server doesn't support multiple columns with auto incrementing integers. You'd need to research a number of strategies for inserting it.
A number are listed here and here. Essentially make StoreNumber a function of StoreID with Computed Columns, or use an independent Sequence:
ALTER TABLE Store DROP COLUMN StoreNumber;
GO
ALTER TABLE Store ADD StoreNumber AS StoreID + 550000;

One-to-Many relation to existed table in EF6: The ALTER TABLE statement conflicted with the FOREIGN KEY constraint

So now I'm trying to use Code first approach with a couple of existed tables.
So before now I have an existed table with model:
[Table("Existed1")]
public class TimeSerieEntity
{
[Key]
[Column(Order = 0)]
[StringLength(3)]
public string TsId { get; set; }
[Key]
[Column(Order = 1, TypeName = "date")]
public DateTime Date { get; set; }
public double Value { get; set; }
}
And this entity illustrate time series element. So Now I need to add new Entity which has One-to-Many relation with this data. So I add class
public class TSRootEntity
{
[Key]
[StringLength(3)]
public string Code { get; set; }
public virtual ICollection<TimeSerieEntity> Values { get; set; }
}
and change TimeSerieEntity to this one:
[Table("Existed1")]
public class TimeSerieEntity
{
[Key, ForeignKey("TSMD")]
[Column(Order = 0)]
[StringLength(3)]
public string TsId { get; set; }
[Key]
[Column(Order = 1, TypeName = "date")]
public DateTime Date { get; set; }
public double Value { get; set; }
public virtual TSRootEntity TSMD { get; set; }
}
and add the following mapping:
`modelBuilder.Entity<TSRootEntity>()
.HasMany(c => c.Values)
.WithRequired(ts => ts.TSMD)
.WillCascadeOnDelete(false);
But when I trying to run migration it fails with error:
{"'PK_dbo.Existed1' is not a constraint.\r\nCould not drop constraint. See previous errors."}
Please, help me to fix this.
For some reason it's try to use PK_dbo.Existed1 but there is no such Constraint in DB, but there is PK_Existed1 Why EF add this dbo prefix?
UPD2:
I solved 1st problem just with renaming PK constraint. But now I have different exception:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_dbo.Existed1_dbo.TSRootEntity_TsId". The conflict occurred in database "testdb", table "dbo.TSRootEntity", column 'Code'.
Ok. Found the problem. So last error caused because of Existed1 already have data, and TSRootEntity is empty. So it's try to map actuall foreign keys, to non existed primary keys. And that's make it fails.
So to solve that, we need prefill TSRootEntity as well. The question is - what is the most elegant way to do that?

nhibernate mapping many rows to one object

i have a rather difficult mapping problem.
EDIT: reformulated descritpion
for historical reasons texts are not stored in a column as text, instead they are saved in tables. i have several tables with following structure:
TABLE SomeEntityTexts
(
id serial NOT NULL,
key character varying(10), // \
linenumber integer, // / unique constraint
type smallint,
length smallint, // actual length of content string
content character varying(80),
PRIMARY KEY (id)
)
text is saved as lines with arbitrary length, different für each entity and sometimes even for different texttypes in one table.
i would like to map them to classes which handle these quirks inside and in mappings.
my solution so far:
a hidden collection and a dummy object which should be readonly. For loading there are always valid Text-objects because persisting the inner collection creates them.
internal class Textline
{
public virtual int Id { get; set; }
public virtual TextType Type { get; set; } // Enum
public virtual int Linenumber { get; set; }
public virtual string Text { get; set; }
}
public class Textmodule
{
public virtual int Id { get; set; }
public virtual string Key { get; set; } // Unique
public virtual TextType Type { get; set; } // Enum
protected internal virtual IList<Textline> Textlines { get; set; }
public virtual string Text
{
get { Textlines.select(t => t.Text).Aggregate(/* ...*/); }
set { /* split text to lines with max 80 chars and feed to Textlines*/}
}
}
public TextmoduleMap()
{
Table("textmodules");
ReadOnly(); // problem: shouldnt insert and update at all, but does insert
Where("linenumber = 1"); // starts with 1
// doesnt matter because it shouldnt be saved
Id(text => text.Id, "id").GeneratedBy.Custom<SimpleGenerator>();
Map(text => text.Key);
HasMany(text => text.Textzeilen)
.Table("textmodules")
.PropertyRef("Key")
.KeyColumn("key")
.Component(c =>
{
c.Map(line => line.Text)
.Columns.Add("content", "length")
.CustomType<StringWithLengthUserType>();
c.Map(line => line.Linenumber, "linenumber");
})
.Cascade.AllDeleteOrphan()
.Not.LazyLoad();
;
}
My problem is, that Readonly doesnt prevent nhibernate from inserting it on save. Is there anything i can do to get it work or does someone has a better idea for a more sane domain object?
Edit2: I fiddled with SQLInsert("SELECT 1"); but i get exception "unexpected rowcount -1, expect 1"
thanks for your time
i found a rather ugly way which is probably not very portable
public TextmoduleMap()
{
...
ReadOnly();
SqlInsert("DROP TABLE IF EXISTS temp; CREATE TEMP TABLE temp(id int); INSERT INTO temp (id) VALUES (1);");
SqlDelete("DROP TABLE IF EXISTS temp; CREATE TEMP TABLE temp(id int); INSERT INTO temp (id) VALUES (1);");
...
}
Better ways are still welcome