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; }
...
}
Related
In a professional social network, how would I represent connections between users? (like Linkedin) Should I create a connection class for which there would be an instance for every connection between 2 users or is that redundant? Should the user class instead have a self-association (reflexive association)?
Your User class would have a collection of Followings:
public class User
{
// ... the other code is omitted for the brevity
public IEnumerable<User> Followings { get; set; }
}
So if your database has the Following table:
CREATE TABLE Followings(
User_Id INT NOT NULL,
Following_Id INT NOT NULL,
DateCreated DATE NOT NULL,
);
Do not forget to create constraints and foreign keys in your table. Then it is possible to have Following class:
public class Followings {
public UserId int { get; set; }
public FollowingId int { get; set; }
public DateCreated DateTime { get; set; }
}
and then you can write easily the following query:
select * from Following where UserId = x.id -- or vice versa
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.
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?
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.
I have the following classes:
public class Event
{
public virtual Guid Id { get; set; }
public virtual string UserName { get; set; }
public virtual EventId EventId { get; set; }
}
public class EventId
{
public virtual Guid EventGuid {get; private set;}
}
I am using a fluent NHibernate automapping in order to map my classes and I override specific properties when needed.
Class: Event is in s_typesToMap and class: EventId is in s_components.
As a result I get the following table generated:
create table "Event" (
Id UNIQUEIDENTIFIER not null,
UserName NVARCHAR(255) null,
EventIdentifierEventGuid UNIQUEIDENTIFIER null,
primary key (Id)
)
I want to create an index on EventIdentifierEventGuid which is a property in Event component.
I tried to do it as follows:
.Override<Event>(obj => obj.Map(x => x.EventId.EventGuid).Index("EventId_index"))
When I generate the ddl I get the following:
create index EventId_index on "Event" (EventGuid)
The expected result should be an index on EventIdentifierEventGuid instead of EventGuid
How can I do it?