SQL - REST - Storing data and retrieving it using friendly IDs - sql

UPDATE 09/06/2018
My models looks like this:
public class Activity
{
public int Id { get; set; }
public List<Additive> Additives { get; set; }
}
public class Additive
{
public int Id { get; set; }
public int ActivityId { get; set; }
public Activity Activity { get; set; }
}
Original Question
I'm developing a RESTful API and i want to do it the cleanest way possible.
Currently i'm working on data retrieving. So i got this
If i create a new resource called activity and it has an array of objects, lets say (hardcoded, not representative):
{
"name": "act1",
"objects": [
{ "obj1":"val1" },
{ "obj2":"val2" }]
}
I'll could add or delete objects from my array.
Now, my question is, if i want to access them with an url like this:
Api/activity/1/objects/2
Which is the correct way to tell MySQL that this object is my 2th object of the list?
Or maybe i should select ALL objects of Act1 on the backend and filter them to retrieve just the 2th one.

It's pretty important that resources in your REST service have stable urls. So to figure out what 'second' is, you really need to think about what it means to be second in the list.
Are you ordering by something? If so, it's probably a bad idea to use this structure because adding a new entry can change the order and what was 'second' before might no longer be in the future.
The best thing you can do is add some kind of new id for these entries so accessing a specific resource by uri will always return that resource (or 404, etc).

I finally found the answer i were looking for.
mysql two column primary key with auto-increment
This is a MyISAM engine feature.
For MyISAM and BDB tables you can specify AUTO_INCREMENT on a secondary column in a multiple-column index. In this case, the generated value for the AUTO_INCREMENT column is calculated as MAX(auto_increment_column) + 1 WHERE prefix=given-prefix. This is useful when you want to put data into ordered groups.
In my case, this query does the job
CREATE TABLE additive (
id INT NOT NULL AUTO_INCREMENT,
activity_id INT NOT NULL,
other_column VARCHAR(30) NOT NULL,
PRIMARY KEY (activity_id, id)
) ENGINE=MyISAM;

Related

Problem With Inserting Record And Assigning Primary Key EF Core 3.0

I have a simple model record with a key "Id" that I'm adding to a EF Entity. It worked through Core 2.1 but now fails with the error:
SqlException: Cannot insert explicit value for identity column in table 'SpeakerRecs' when IDENTITY_INSERT is set to OFF.
The Model is defined as follows:
namespace WebAppCore.Models
{
public class SpeakerRec
{
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string ImageUrl { get; set; }
}
}
The Code that does the insert is this and it fails on the save changes call.
foreach (var speaker in speakerRecs)
{
_context.SpeakerRecs.Add(speaker);
}
_context.SaveChanges();
I see notes about breaking changes in Core 3 and the problem is somehow around ValueGeneratedNever() but can't figure it out. I've not used EF for a while and was not planning on re-learning it. I was hoping my old code would continue to work.
If you want to manually insert the Id , you can use [DatabaseGenerated(DatabaseGeneratedOption.None)] . The None option prevents values from being generated by the database automatically in cases where they would otherwise be created :
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
If you have created the migration before , when create new migration and update database , you may get exception like To change the IDENTITY property of a column, the column needs to be dropped and recreated , you can :
Delete the actual database
Delete the Migrations folder in your project and clean the project
Create a new migration with dd-migration <migration_name> in the Package Manager Console and then Update-database .
You are inserting explicit values in the Id column, which is an identity column. To insert value explicitly into the identity column you have to turn on the identity insert.
If your database is automatically inserting value for the Id column, you should not specify them externally from your code.
Update your edmx file to reflect any changes you may have made in the database. If the database automatically assigns the value, you should see the "IsDbGenerated=true" attribute in your designer file under that property. If it's not there, you can add it manually.
Reference

Renaming a table and a foreign key fails using ef6

I use EF6 and code first migrations. I have a two tables
public class Team {
public int Id { get; set; }
public string Name { get; set; }
}
public class TeamMember {
public int Id { get; set; }
public string Name { get; set; }
public Team Team { get; set; }
public int TeamId { get; set; }
}
I want to rename TeamMember to TeamMemberDeprecated and add a new tabled named TeamMember with some differences to the table layout. The main reason I am creating a new table is data. I want to save all of the data in the current TeamMember table so I need to rename it, and I want to transfer only the specific data I need to the new TeamMember table.
When I add the migration it looks like this
RenameTable(name: "dbo.TeamMember", newName: "TeamMemberDeprecated");
What it doesn't do is change the name of the foreign key property from FK_dbo.TeamMember_dbo.Team_TeamId to FK_dbo.TeamMemberDeprecated_dbo.Team_TeamId.
This presents a problem when I go to create the new TeamMember table because the foreign key FK_dbo.TeamMember_dbo.Team_TeamId already exists in the database.
I tried dropping the foreign key and renaming it, but this doesn't do anything and when I run the migration -verbose I see why it's expecting the foreign key to be null. I want to keep the data, but perhaps my approach is wrong.
Any suggestions are welcome, thanks.
Let EF rename the table, then go to SQL management studio and manually rename the foreign keys.
Go back to EF, make the changes, run the migration and let EF create the new foreign keys
Don't forget to backup your DB
In EF Core 5.?? there should be a few new commands (see EFCore GitHub Pull):
RenamePrimaryKey
RenameUniqueConstraint
RenameForeignKey
However, it seems that these will drop and recreate the key/constraint. In MSSQL this is not only unnecessary, but very costly. When the constraint is reapplied the database much check that each item is unique or present in the foreign table. If you can help it, do not do this.
Instead I recommend the below. You must specify the schema in the first parameter for the new name, but not in the second. The square brackets will help if any lunatic has put dots in table or constraint names:
migrationBuilder.Sql("sp_rename '[dbo].[PK_TeamMemberDeprecated]', '[PK_TeamMember]'");
It works the same for foreign keys:
migrationBuilder.Sql("sp_rename '[dbo].[FK_TeamMemberDeprecated_TeamID]', '[FK_TeamMember_TeamID]'");

Entity Framework Update Key

[Table("tblClients")]
public class ClientsTbl
{
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ClientID { get; set; }
[Key]
public int userid { get; set; }
}
If i have old data (from unknown source) to import which has userid that related with other tables for example invoice etc without using Foreign Key, how can i design my DB model? If i would design like that insert must be like that :
Random a = new Random();
ClientsTbl c = new ClientsTbl()
{
userid = a.Next(-1000, -1),
}
dataContext.Clients.Add(c);
dataContext.SaveChanges();
var client = dataContext.Clients.FirstOrDefault(x => x.userid == c.userid);
if(client!=null)
{
client.userid = c.ClientID;
}
dataContext.SaveChanges();
after inserting a record I need to update "userid" : `` And it gives an error
The property 'userid' is part of the object's key information and cannot be modified.
If i would change all operations to Stored Procedure's (insert and update) everything is ok.
Why Entity Framework doesn't allow to update Key ? (Sql server does)
This is due to the fact that you're referencing the same object. This has been asked before and answered here:
The property 'Id' is part of the object's key information and cannot be modified
I hope this helps you.
OO paradigm has this thing about "object identity". RM does not have this (not in the sense that every identifier of a thing MUST MANDATORILY remain unchanged during the whole lifetime of the thing it identifies).
Tools that attempt to bridge the gap between the two are therefore inevitably faced with a kind of mismatch, and must do one of two things to address it : (a) break the OO paradigm of cast-in-concrete-immutable identity, or (b) enforce the OO paradigm and rule out perfectly legitimate RM operations.
Most if not all of them opt for (b) because that is the easiest way out, at least for the developers.

Composite Foreign Key to Dynamic Table, Bad Practice

First off, I am not a DBA, I am a C# developer. I am working on a pretty complex web application and I want to start with a solid database. So here is my issue:
I am trying to create a Settings table that will hold settings for multiple objects. ie: User settings, Season settings, League settings, Team settings.
Instead of creating a table for each of those I would like to keep everything in the Settings table but I can't figure out how to create the foreign key.
My approach is to have three columns in the Settings table: TableName PrimaryKey ID. These three columns would create a composite key that would reference the appropriate object. Is my approach considered bad practice or am I on the right track? Is there a way I can do this that will still work with entity framework?
Here is my way of handling this.
In this diagram, ConfigId is primary key which is used as an FK in Person table as EyeColor, BloodType, PersonType and many more. These columns also hold a Check constraint to ensure no value apart from eye color or corresponding column get stored based on ConfigType. However this comes at a cost of broader datatype which may be smallint or int instead of tinyint.
Only difference is, I am calling these settings as ConfigType in your case {User, Team, Season etc.} and any extension can be done by inheritance concept by creating another table using ConfigId as FK in child table.
If you use inheritance, by default EF will use one table for the entire hierarchy. This is known as Table Per Hierarchy or TPH
public abstract class Setting
{
public string Key { get; set; }
public string Value { get; set; }
}
public class UserSetting : Setting
{
public int UserId { get; set; }
public virtual User User { get; set; }
}
public class SeasonSetting : Setting
{
public int SeasonId { get; set; }
public virtual Season Season { get; set; }
}

How to use NHibernate with entity spread over multiple tables?

I have pre-existing tables, using a kind of open schema. I have an Item table, and various entities are classified as Items, and then have properties stored in Item property tables. A single entity type may have fields stored in multiple tables. We expose entities with views. So, most entities correspond to a view, and then when we insert/update we have to systematically update the tables or use stored procedures.
I'm trying to determine if NHibernate will gain us anything over our custom-built repositories (which follow a factory pattern). Right now, I'm seeing great difficulty in getting NHibernate to deal with this kind of database schema. The way I see it, we'd either have to completely refactor our database to follow NHibernate's conventions, or completely refactor or entities somehow.
I'm not seeing much in the documentation about how to do this, except for the very simplest of examples that involve databases that more or less follow NHibernate's conventions.
Here's a representative database diagram. We have Episode as an entity that pulls info from Item, IP_Episode, IP_EpisodeBroadcastInfo, IP_Show, etc. to build all the fields that it needs.
You mention conventions. That is a Fluent NHibernate concept, and yes, what you are doing is not exactly in line with Fluent NHibernate's existing conventions. However, it is well within NHibernate's capabilities. NHibernate excels at being able to be mapped to all sorts of different database schemas. Don't feel constrained to the way Fluent NHibernate wants you to go. I'm not saying don't use Fluent NHibernate. If you are consistent and reasonable in your database schema, you can write your own conventions to match.
To illustate NHibernate's flexibility, let's assume we have a table structure similar to this:
create table Episode (
Id int not null primary key,
NumberInSeries int null
);
create table Show (
Episode_id int not null primary key,
Title nvarchar(100) not null,
foreign key (Episode_id) references Episode (Id)
);
create table Broadcast (
Episode_id int not null primary key,
InitialAirDate datetime not null,
foreign key (Episode_id) references Episode (Id)
);
One row in Episode corresponds to zero or one rows in Show and zero or one rows in Broadcast. You could model this type of relationship several different ways in .NET. Here are the various options available to you via NHibernate:
1. Inheritance
public class Episode
{
public virtual int Id { get; set; }
public virtual int? NumberInSeries { get; set; }
}
public class Show : Episode
{
public virtual string Title { get; set; }
}
public class Broadcast : Episode
{
public virtual DateTime InitialAirDate { get; set; }
}
Use this when you want to model a relationship that does not change. If an Episode is a Show, it is always a Show. Also, this modeling would imply that an Episode cannot be both a Show and a Broadcast. I don't believe this is what you want, but you may find it useful elsewhere in your model.
For more info, see...
Official documentation on inheritance mapping
Ayende's blog post on inheritance mapping
2. one-to-one
public class Episode
{
public virtual int Id { get; set; }
public virtual int? NumberInSeries { get; set; }
public virtual Show Show { get; set; }
public virtual Broadcast Broadcast { get; set; }
}
public class Show
{
public virtual Episode Episode { get; set; }
public virtual string Title { get; set; }
}
public class Broadcast
{
public virtual Episode Episode { get; set; }
public virtual DateTime InitialAirDate { get; set; }
}
This gives you more control over which tables actually contain a row associated with a given Episode, because you can set episode.Broadcast = null for example. It's also fine to have both Show and Broadcast information for a given Episode.
For more info, see...
Official documentation on one-to-one
Ayende's blog post on one-to-one
3. join
public class Episode
{
// These properties come from the Episode table...
public virtual int Id { get; set; }
public virtual int? NumberInSeries { get; set; }
// This one comes from the Show table.
public virtual string Title { get; set; }
// This one comes from the Broadcast table.
public virtual DateTime InitialAirDate { get; set; }
}
This is a nice and simple way to represent the data, but you do not get control over whether on not rows are inserted into the Show and Broadcast tables or not.
For more info, see...
Official documentation on join
Ayende's blog post on join
Since you said, "A single entity type may have fields stored in multiple tables", it sounds to me like join should be able to handle the way you currently have things modeled.