Is it possible to use arrays in Entity Framework with PostgreSql?
Suppose, for instance, we had the POCO class
public class MyTable
{
[Key]
[Column("gid")]
public int Gid { get; set; }
[Column("name")]
public string Name { get; set; }
[Column("email")]
public string Email { get; set; }
[Column("somedata")]
public int[] SomeData { get; set; }
}
At this point Entity Framework simply does not create the column "somedata" and skips it. Is there a way to do this anyway? And by that I mean not having to use a separate table. Postgres arrays come in handy at times where you want to store a small or limited number of values into a single column.
It's possible to do this if you use Entity Framework Core with the Npgsql EF Core provider.
The code-first approach would be:
[Column("somedata", TypeName = "integer[]")]
public int[] SomeData { get; set; }
Related
Assume I've read and googled, and I still don't know what I'm doing incorrectly. Whenever I try to execute
_dbContext.Set<T>().Add(aMediaObjectWithAssociatedProvider);
_dbContext.SaveChanges();
I get the dreaded efcore violation of primary key constraint reference table
I have a class as such:
public class Media : BaseModel
{
public virtual string Title { get; set; }
public virtual string? Description { get; set; }
public virtual string Source { get; set; }
public virtual Guid? MediaTypeId { get; set; }
public virtual Guid? ProviderId { get; set; }
public virtual DateTime? StartDate { get; set; }
public virtual DateTime? EndDate { get; set; }
public virtual Provider? Provider { get; set; }
}
The BaseModel class is
public abstract class BaseModel : IBaseModel
{
public virtual Guid Id { get; set; }
}
The Provider class is as such:
public class Provider : BaseModel
{
public virtual string Name { get; set; }
public virtual string? ApiUsername { get; set; }
public virtual string? ConfigurationSection{ get; set; }
}
My DBContext has the following:
protected override void OnModelCreating(ModelBuilder mb)
{
mb.Entity<Media>().HasKey(x => x.Id);
mb.Entity<Media>().HasOne(p => p.Provider).WithOne().HasForeignKey<Media>(x => x.ProviderId);
}
The code for inserting a new object is as follows:
public T Insert(T oneObject)
{
try
{
// Ensure the entity has an ID
if (oneObject.Id == Guid.Empty)
{
oneObject.Id = Guid.NewGuid();
}
_dbContext.Set<T>().Add(oneObject);
_dbContext.SaveChanges();
}
catch (Exception error)
{
_logger.LogError(error.Message, error);
}
return oneObject;
}
Assume that providers are static, in a sense that they already exist in their table, and I don't want to add new providers when I save media... Media just needs to have a provider.
I know exactly what is happening (the model, after travelling through json back through the api to the server is losing context, but I'm also trying to build a repository type of system where I don't have to build complex save logic for every object. (hence why i'm hand wringing over adding code that loads existing providers).
This problem specifically began rearing its head when I was saving new Media objects into the database with existing Providers. I am still mulling over how to look up children dynamically, but i'm not quite there yet.
I've been at this for so long, i'm about ready to give up on efcore relations and just rebuild the models as single objects, and handle all of the manipulation in javascript. And I don't like this idea.
I know for a fact that there will be questions for more code, but please let me know what. Again, I'm just stepping into .net core / ef core so this code-first is a little confusing for me. Thanks
You may have 2 options to try. Do backup your whole project and database beforehand. Clone your database to another database name. Try these either one option using new cloned database for testing.
No.1
Set "newid()" without quotes in your ID's default value in sql server. So you don't need to use Guid.NewGuid() in code every insert. newid() will auto generate GUID.
No. 2
How about removing primary key from ID (GUID) and then creating new column "UID" (running number) and set UID (running number) as primary key and enable its identity? You need to change all other tables too. And re-link UID each other if you use relationship. This way, your UID will not have existing number when insert.
I want to update a mediate table's primary keys. This post suggests to take another primary key and don't change it, but we're using our tables in other non-EF projects, I didn't designed them and I'm not able to change them. Do I have any other option? Anything? Even deleting the old record and inserting a new one. I just don't know how to retrieve the old values.
This is my class:
public class ZChangeUnits : User
{
[Key]
[Column(TypeName = "VARCHAR", Order = 0), StringLength(4)]
public string CCode1 { get; set; }
[ForeignKey("CCode1")]
public virtual ZUnits ZUnits1 { get; set; }
[Key]
[Column(TypeName = "VARCHAR", Order = 1), StringLength(4)]
public string CCode2 { get; set; }
[ForeignKey("CCode2")]
public virtual ZUnits ZUnits2 { get; set; }
[Column(TypeName = "NUMERIC")]
[DecimalPrecision(18, 5)]
public decimal NZarib { get; set; }
}
UPDATE
I've posted the schema below, the left table is used for unit conversion. This is actually the suggested method in this answer.
I can't think of any other way to implement that. Whether I should update my table's design or some EF code will do the job. Any help and solution is welcome. :)
I'm trying to use the entity framework to communicate with my existing DB. This is thus DB first. Using sql server and c#. The problem is that I would like to use a sequential GUID, generated by the database.
Each time I run the code, my controller pastes the GUID assigned to lutRoughagePhysicalSiloId to the DB (most of the time lutRoughagePhysicalSiloId is just an empty GUID (000..) since I don't fill it). As far as I can see, this should not be happening since I use [DatabaseGenerated(DatabaseGeneratedOption.Identity)].
Any Ideas?
SQL code
CREATE TABLE [dbo].[lutRoughagePhysicalSiloType]
(
[RoughagePhysicalSiloTypeId] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY UNIQUE DEFAULT NEWSEQUENTIALID(),
[PhysicalSiloTypeName] NVARCHAR(50) NOT NULL UNIQUE
)
(Notice the Default value newsequentialId() that gets generated as default by sql server)
Automatic created modelview (DB first):
namespace guiIlvoDairyCowBarn.Models
{
using System;
using System.Collections.Generic;
public partial class lutConcentratePhysicalSiloType
{
public lutConcentratePhysicalSiloType()
{
this.lutConcentratePhysicalSiloes = new HashSet<lutConcentratePhysicalSilo>();
}
public System.Guid ConcentratePhysicalSiloTypeId { get; set; }
public string PhysicalSiloTypeName { get; set; }
public virtual ICollection<lutConcentratePhysicalSilo> lutConcentratePhysicalSiloes { get; set; }
}
}
Buddy class
namespace guiIlvoDairyCowBarn.Models
{
[MetadataType(typeof(lutRoughagePhysicalSiloMD))]
public partial class lutRoughagePhysicalSiloType
{
public class lutRoughagePhysicalSiloMD
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public System.Guid RoughagePhysicalSiloTypeId { get; set; }
[Required, DisplayName("Physical silo type")]
public string PhysicalSiloTypeName { get; set; }
public virtual ICollection<lutRoughagePhysicalSilo> lutRoughagePhysicalSiloes { get; set; }
}
}
}
what is a Buddy class suppose to mean?
Using both [Key] and the [DatabaseGenerated(DatabaseGeneratedOption.Identity)] should work and ignore any user provided value. After saving to the DB the property should have the DB generated Guid.
Your class lutConcentratePhysicalSiloType has no EF data annotations and if saved would take the values you provided. NewSequentialId() is a default and without any EF data annotations the DB row will get whatever the value you specify in the C# class.
I have two tables:
public AdminTest()
{
this.AdminTestQuestions = new List<AdminTestQuestion>();
}
public int AdminTestId { get; set; }
public string Title { get; set; }
public virtual ICollection<AdminTestQuestion> AdminTestQuestions { get; set; }
}
public partial class AdminTestQuestion
{
public int AdminTestQuestionId { get; set; }
public int AdminTestId { get; set; }
public System.Guid QuestionUId { get; set; }
public virtual AdminTest AdminTest { get; set; }
}
I am using the following EF6 code to add a new adminTest (with its adminTestQuestions) to the
database:
public async Task<IHttpActionResult> Post([FromBody]AdminTest adminTest)
{
db.AdminTests.Add(adminTest);
foreach (AdminTestQuestion adminTestQuestion in adminTest.AdminTestQuestions)
{
db.AdminTestQuestions.Add(adminTestQuestion);
}
await db.SaveChangesAsync(User, DateTime.UtcNow);
return Ok(adminTest);
}
I have similar but more complicated code to deal with the case where questions are added or removed from the adminTest. All my code works but it would be very good if EF was able to do what I needed rather than my having to add many lines of code.
Can anyone tell me if there have been any changes to EF6 or if any changes are planned to EF7 that will allow it
has noted on the ef7 github they seams to have added some neat code that add primary key entity.
but it is still not clear as to if it will be a common thing for children collection in an entity.
Git hub Entity Framework Design Meeting Notes
but for EF6 you could use a Generic Repository to make all the work for you. (since you can't extend DbContext directly)
assuming db is a DbContext
you could use this -> : Accessing a Collection Through Reflection
then find all Property from a class T that contains ICollection<> and do a foreach on the item of the ICollection Property then do db.Set.Add(proprietyChild) on it
that would eliminate the need for always repeating the same add child to entity code.
some people already did implement a solution thou : Automated updates of a graph of deached entities
I'm writing an ASP.net MVC3 application using Entity Framework Code First and SqlCe4.
I have been designing several models, and found one that is turning out to be interesting. This is what I have so far:
public class Preference
{
public int PreferenceId { get; set; }
[Required]
public int StudentId { get; set; }
public virtual Student Student { get; set; }
[Required]
public int PresentationId { get; set; }
public virtual Presentation Presentation { get; set; }
[Required]
public int Rank { get; set; }
}
I however, need a unique constraint or index, because for a particular student, I want them to have to have a list of preferences, but the PresentationId needs to be unique for each student. Is there a way to do this via Code First or some validation attribute?
This sounds like I'm going down the branch of a many to many relationship with the Preference object being an intermediary, to add the Rank property. However, I can't seem to find how to make sure that the values are unique. Is the best way really to manually just add a unique index to the database outside of EF?
Currently(ie EF 4.1) EF does not have an Attribute or configuration mechanism to create unique indexes.
However if you are using Database Initializer you can create it manually
public class MyInitializer : IDatabaseInitializer<MyContext>
{
public void InitializeDatabase(MyContext context)
{
if (!context.Database.Exists() || !context.Database.ModelMatchesDatabase())
{
context.Database.DeleteIfExists();
context.Database.Create();
context.ObjectContext.ExecuteStoreCommand("CREATE INDEX IX_Preference_PresentationId ON Preference ( PresentationId )");
}
}
}
Or execute it outside the Initializer.
I'm not sure how long the feature has existed, but in EF5, you can use the CreateIndex and DropIndex method in your Up() and Down() methods. This allows you to create unique indexes, which function almost identically to unique constraints, in EF's own language.
public partial class UniqueIndexMigration
{
public override void Up()
{
// Create new unique index
this.CreateIndex("dbo.TableName", new[] { "Col1", "Col2", "Col3" }, true, "IX_TableName_Col1_Col2_Col3");
}
public override void Down()
{
// Drop unique index
this.DropIndex("dbo.TableName", "IX_TableName_Col1_Col2_Col3");
}
}
The true, seen above, is the parameter that specifies that it's a unique constraint. Sadly, these constraints are not honored when making further migrations later on (EF won't drop them for you if you change the underlying schema), but my hope is that by using the EF API, your code will get an upgrade for free when this feature is finally added.
Going with what Eranga was saying, I ended up making it work similarly, but like this:
I used the following code in my DataContext class:
public class StudentRegistrationContext : DbContext
{
public StudentRegistrationContext()
{
Database.SetInitializer(new StudentRegistrationDatabaseInitializer());
}
public DbSet<Student> Students { get; set; }
public DbSet<Teacher> Teachers { get; set; }
public DbSet<Presenter> Presenters { get; set; }
public DbSet<Presentation> Presentations { get; set; }
}
In the Database Initializer class, I used the following:
public class StudentRegistrationDatabaseInitializer : DropCreateDatabaseIfModelChanges<StudentRegistrationContext>
{
protected override void Seed(StudentRegistrationContext context)
{
base.Seed(context);
context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX UX_Preferences_StudentId_PresentationId ON Preferences (StudentId, PresentationId)");
}
}
See answear that implements the Unique constraint with a Custom ValidationAttribute:
https://stackoverflow.com/a/10566485/1133338