EF Code First Auto generate column ID - c#

I was wondering if it where at all possible to have a Key that auto generated like this:
CBE_2012_1
CBE_2012_2
CBE_2012_3
CBE_2013_1
CBE_2013_2
CBA_2013_1
CBA_2013_2
CBC_2013_1
I now have this in my class, with ID is Id with autonumbering:
[Key]
public int Id { get; set; }
public DateTime Date { get; set; }
public string Code { get; set; }
public string Name { get; set; }
But I would like to have this with Number being the KEY & format: Code_Year_Id:
[Key]
public string Number { get; set; }
public DateTime Date { get; set; }
public string Code { get; set; }
public string Name { get; set; }
Can anybody help me with this?
Or does anybody have helpfull documentation that can provide me with a decent solution?
Before I save a new item I could just create a number myself (In code), but there could be 2 people saving a new item # the same time and I do not want an exception on duplicate key..
Zarkos

Generally, using a meaningful value for a key is a bad idea. You will be much better off using a sequential value who's only purpose is to ensure referential integrity. If for not other reason than: if your key is not sequential, you are going to get a lot of fragmentation on your index as you insert new records.
If you do want to be sure that you get a unique value, you could create a SQL table that holds your last value, and then a UDF or sproc that takes the current value in that table, increments it to the next value and then returns that value.

Related

Foreign Key int Array C#

I have related table. How can I keep the relationship in this table as an array?
public int TreatmentId { get; set; }
[ForeignKey("TreatmentId")]
public virtual Treatment Treatment { get; set; }
I want to be able to give the TreatmentId here like this;
When I make an array and try to migrate, I get the following error;
The property 'ContactPage.TreatmentId' is of type 'int[]' which is not supported by the current database provider. Either change the property CLR type, or ignore the property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
public int[] TreatmentId { get; set; }
[ForeignKey("TreatmentId")]
public virtual Treatment Treatment { get; set; }
You cannot save an integer array as FK, however I have seen people adding comma separated values as string, but this design is a very bad practice and will cause you many problems.
You need to have a third Table (one of your tables is Treatments, assuming the other one is Patients), like PatientsTreatments:
public class PatientsTreatments
{
public int PatientId { get; set;}
public int TreatmentId { get; set;}
}
and then you need to add a new record for each treatment.

[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.

select query to get all values based on distinct values using linq

I have n number of services and under each service there will be 2 routes(some times more than 2). Under each route there are n number of stops. I am getting values from db as a table in below column order
ServiceId, Service Name,serviceLine color,RouteId, Route Name, Stop Id, Stop Name, Latitude, Longitude.
I want to convert it an object list of below format
public class Service
{
public string ServiceId { get; set; }
public string ServiceName { get; set; }
public string ServiceLineColor { get; set; }
public List<RouteData> RouteList { get; set; }
}
public class RouteData
{
public string RouteId { get; set; }
public string RouteCode { get; set; }
public string RouteName { get; set; }
public List<StopData> stopList { get; set; }
}
public class StopData
{
public string StopCode { get; set; }
public string StopName { get; set; }
public string Latitude { get; set; }
public string Longitude { get; set; }
public string StopType { get; set; }
}
Is there any easy way in linq to convert data in to below format? I wanted to avoid looping.. since i am getting nearly 1k records from db. Please help me to solve this issue.
Or is it best to use db calls to format data. i didn't prefer that because if there is 50 services i need to do 50 db calls and again have to do data formatting logic.
To avoid looping over the data structure each time, you could build up additional dictionaries that provide fast access of the objects by id:
var myServiceIndex = new Dictionary<string, Service>()
var myRouteDataIndex = new Dictionary<string, RouteData>()
Service service;
RouteData routData;
foreach (var record in databaseRecords)
{
if (myRouteDataIndex.TryGetValue(record.RouteId, out route))
{
// add stop data
}
else if (myServiceIndex.TryGetValue(record.ServiceId, out service)
{
// add route data
// add stop data
}
else
{
// add service
// add route data
// add stop data
}
}
You have a number of stops, and for each stop entry in database you have to map it to a C# object. In this case, looping is inevitable, as far as I see. Linq, and eg. entity framework, use looping internally.
One option is to use entity framework or Linq to SQL. It will give you strong type classes representing each DB table. But you have to change your DB schema and use foreign keys to link service, route, and stops.
C# code would look exactly like yours, which is auto generated by entity framework and in-sync with DB schema.
Second option is to convert manually. Note, your current schema doesn't complient with Third normal form. If you don't want to change your schema, you could read and generate them using group by clause.

How to get mysql char column type from C# Entity Framework Code First Model

I have just done the equivalent of Hello World by creating an Entity Framework Code First model (I have written other C# programs but not with Entity Framework). I created a model like this:
class Preferences
{
[Key]
public string StationName { get; set; }
[MaxLength(30)]
public string MainDatabase { get; set; }
[MaxLength(30)]
public string DefaultSequence { get; set; }
}
and then had a little routine to add a record
var newPrefs = new Preferences
{
StationName = "MATT",
DefaultSequence = "NONE",
MainDatabase = "NONE"
};
Preferences prefs = foo.Preferences.Add(newPrefs);
which then tries to create the database and fails when adding the primary key with the error
"BLOB/TEXT column 'StationName' used in key specification without a key length"
because it uses the data type "mediumtext" instead of CHAR or VARCHAR and MySQL can't use that type for a key.
Is there a method that is still more-or-less database agnostic that will tell MySQL to use the preferred type for the key column? Or do I just have to give up and make an integer key?
I also tried variations of the design like this but nothing worked.
class Preferences
{
[Key,DataType("CHAR"),StringLength(30)]
public string StationName { get; set; }
[MaxLength(30)]
public string MainDatabase { get; set; }
[MaxLength(30)]
public string DefaultSequence { get; set; }
}
Thanks for your help.
Try fluent mapping column type maybe:
modelBuilder.Entity<Preferences>()
.Property(p => p.Id)
.HasColumnType("CHAR(30)");
I think this is equivilent of [Column(TypeName = "CHAR(30)")] but not certain it's the same.
Edit: As per Matt's testing, length is seperate and, "char" may be case sensitive(there are a lot of settings in MySQL and other engiens related to case sensitivity in identifiers, and OS can play a part sometimes, so may vary): [Column(TypeName="char")][MaxLength(30)]
I would suggest you apply a commonly accepted practice in relational database design, which is to have meaningless primary keys. Meaningless to the business domain that is.
class Preferences
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[MaxLength(30)]
public string StationName { get; set; }
[MaxLength(30)]
public string MainDatabase { get; set; }
[MaxLength(30)]
public string DefaultSequence { get; set; }
}
Additional benefit: now you're free to change the StationName whenever necessary.

search for int id starting with x entity framework 4.1

I currently have an Entity Framework model that collects data from a legacy database and I am currently using an int on my Id properties
I am attempting to build a search box with autocomplete capabilities and want to have the autocomplete function to return a subset of records based on whether the sample id either contains or starts with (final design decision not made yet) and I am running into problems with converting the integer id to a string as I would normally use a recs.Id.toString().StartsWith(recordId) but this is apparently not supported by the Entity Framework
Is there a way around this limitation ?
My code looks like the following
Model:
public class Sample
{
public Sample()
{
Tests = new List<Test>();
}
public int Id { get; set; }
public DateTime SampleDate { get; set; }
public string Container { get; set; }
public string Product { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public virtual SamplePoint SamplingPoint { get; set; }
public virtual SampleTemplate SampleTemplate { get; set; }
public Customer ForCustomer { get; set; }
public virtual ICollection<Test> Tests { get; set; }
}
and the query I am currently trying to apply to this model
[HttpGet]
public JsonResult AutoComplete(string partialId)
{
var filteredSamples =
repo.AllSamples.Where( s =>
String.Compare(s.Status, "A", false) == 0
&& (s.Id.ToString()).StartsWith(partialId)
).ToList();
return Json(filteredSamples, JsonRequestBehavior.AllowGet);
}
Any ideas would be awesome I am out of ideas at this point
No matter what you do, this is going to result in some awful performance on large datasets, because you will not be able to use any indices. My recommendation would be to use a trigger or scheduled task to store the leading digit in a separate field and filter on that.
I ended up adding a view for autocomplete data and converting the data to string in the select statement and this solved my issue
Wild thought: how about your create a computed, persisted column on your database table, that converts your ID (INT) into a string?
Then you could:
put an index on that column
use a simple string comparison on that string column
Basically, you need this:
ALTER TABLE dbo.YourTable
ADD IDAsText AS CAST(ID AS VARCHAR(10)) PERSISTED
Now update you EF model - and now you should have a new string field IDAsText in your object class. Try to run your autocomplete comparisons against that string field.

Categories

Resources