How to auto-generate class field comment to database? Entity Framework code first - entity-framework

I'm using Entity Framework code-first mode, but how to auto-generate class field comments to database?
Example:
[Table("User")]
public class User
{
/// <summary>
/// Id
/// </summary>
public long Id{get;set;}
/// <summary>
/// this is name
/// </summary>
public string name{get;set;}
}
SQL should be like this:
CREATE TABLE User
(
id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'Id',
name VARCHAR(128) NOT NULL COMMENT 'this is name'
)
Does anyone have an idea how to achieve this?

To give a more specific answer besides "not." in the comments.
It's basically not possible to achieve this as comments are not passed over to the compiled object that is taken as the base for generating the migration elements.
In addition consider that the free comment section might contain a comment that might be used as a book (i.e. there's no limitation on comments but there is on comments in the database).
You might consider using a new attribute that might suit your needs, like:
[DbComment('This field is containing bla bla')]
public int FooBar {get; set;}
This might then be incorporated into the database generation process by overwriting the Sql-Generation classes.
The concern by using this approach is still that comments need to be maintained twice.

Related

Npgsql.PostgresException 42703: column "Created" of relation "posts" does not exist

Currently I'm working on a little project with .NET Core and PostgreSQL. For my data acccess, I would like to use Dapper.Contrib. Right now, I'm facing the following problem:
The following snippet shows the CREATE_DATABASE.sql
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE posts (
id UUID DEFAULT uuid_generate_v4 (),
created BIGINT,
value VARCHAR NOT NULL,
PRIMARY KEY (Id)
);
And the following is my model class in .NET Core
[Table("posts")]
public class Post
{
[Column("id")]
public Guid Id { get; set; }
[Column("created")]
public long Created { get; set; }
[Column("value")]
public string Value { get; set; }
}
The insert method looks like this (it is in the base class. In this case T is type of Post):
public void Insert(T entity)
{
_connection.Insert(entity);
}
When trying to insert an Post object, I'm running into following error:
Ein Ausnahmefehler des Typs "Npgsql.PostgresException" ist in System.Private.CoreLib.dll aufgetreten.: '42703: column "Created" of relation "posts" does not exist
When set NpgsqlLogManager.Provider to new ConsoleLoggingProvider(NpgsqlLogLevel.Trace, true, true); there is the following INSERT statement logged:
DEBUG [14313] Executing statement(s):
insert into posts ("Created", "Value") values ($1, $2) RETURNING Id
So, where is the problem here? I thought Dapper.Contrib is doing fine with attributes, but obviously it isn't.
Does anybody know how to fix this issue, except of rename the model properties into lower case?
Thank you so far.
With Dapper.Contrib, there are ways to map table name but apparently, there is no way to map the column name. This feature was planned for 2.x version. Version 2.x is released; but the issue is still open. Looking at the release notes, feature is not yet added.
Please refer to this answer to know about other query generators for Dapper those support column name mapping.
It seems that Dapper.Contrib does not allow to specify a Column attribute (but it does allow to specify a Table attribute). At ticket is open for this case.
But it does support custom column to property mappers.
See this post for more details on how to implement this mapping.

EF Core 3.1 Migrations Not Seeing Changes

I've created a code-fist model for entity framework core. I did an add-migration and noticed somethings weren't correct. So, I removed the migration, made my changes and tried again. After several cycles of add/remove/add/remove... I was seeing things not change.
Here the model I'm having problems with:
namespace CompetenciesDataModel {
/// <summary>
/// This entity represents the different Competencies that an employee may have, plus a comptency may have
/// have skills that are shared across competencies.
/// This entity is a look up table that can only be modifed by an administrator.
/// </summary>
public class Competency {
/// <summary>
/// The primary key for the competencies
/// </summary>
[DatabaseGenerated( DatabaseGeneratedOption.Identity )]
public Guid CompetencyId { get; set; }
/// <summary>
/// The name of the competency
/// </summary>
[Required]
public string CompetencyName { get; set; }
/// <summary>
/// The list of skills that are part of this competency
/// </summary>
public List< CompetencySkillAssoc > CompetenciesAndSkills { get; set; }
}
Notice there are three items. When I do the add-migration, the scaffolding code shows three items, except the third one is called Competencies and not CompetenciesAndSkills. It is of type Guid and then is setup as an index on a column that I didn't create. When I look at the other indexes being created they are being done on the primary key. I've even stated that the CompetencyId is a Key and I still get the same result.
The CompetenciesAndSkills is an association table for a many-to-many relationship with a different table.
There isn't any tables within the DB since it doesn't exist, is there anywhere there's a cache that I'm missing to clear? Or, am I just not understanding something else?
Thanks in advance
The Competency entity is used as a lookup table. Therefore, when I attempted to have the Competency entity as part of a different entity (call it EntityX), the migration created a Foriegn Key within the Competency entity. After realizing that this was a look up and wasn't going to change much (unless some product adminstrator edited).
EntityX had a one-to-many relationship with Competency. Therefore, I created a new entity that contained a key to EntityX and the Competency entity. When I did the migration I didn't have an extra column being made that contained the foriegn key back to EntityX.

EF Code First One-To-One with Join Table

I am trying to configure my model to an existing database, and am running into a problem. The previous developer modeled a one-to-one relationship using a join table. If I have the following classes and database structure below, how can I map this using code first?
public class Title {
public Property Property { get; set; }
}
public class Property {
public Title TitleInsurance { get; set; }
}
tbTitle
-TitleID = PK
tbPropertyToTitle
-TitleID - FK to tbTitle.TitleID
-PropertID - FK to tbProperty.PropertyID
tbProperty
-PropertyID = PK
Code in VB.Net here, but should be easy to translate. Mark primary keys with the Key data attribute. Entity Framework will automatically look for properties named Class + ID, i.e. tbTitleID to assign as primary keys, but since that isn't applicable here, we need the Key attribute.
Overridable properties denote Navigation Properties. In C#, this should be equivalent to Virtual properties. When this navigation property is accessed, Entity Framework will automatically look for valid foreign key relations, and populate the appropriate data.
For a one-to-one relationship, Entity Framework expects that your two tables share the same primary key, as shown by TitleID here.
Public Class tbTitle
<Key()>
Public Property TitleID As Integer
...
Public Overridable Property Property As tbProperty
End Class
Public Class tbProperty
<Key()>
Public Property TitleID As Integer
...
Public Overridable Property Title As tbTitle
End Class
Looking through the fluent API, I don't see any way to map one to one relations through a join table. You might be able to fake it by setting it up as a many to many but then you would need a bit of extra code to ensure that your relation collections only ever have one item in them.

Breeze is trying to update a computed database column

A friend reported a problem with a computed column, Entity Framework, and Breeze
We have a table with a "FullName" column computed by the database. When creating a new Person, Breeze sends the FullName property value to the server, even though it’s not being set at all, and that triggers an error when trying to insert the new Person instance. The database throws this exception:
The column "FullName" cannot be modified because it is either a computed column or is the result of a UNION operator.
Here is the relevant portion of the SQL Table definition:
CREATE TABLE [dbo].[Person](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[FirstName] [varchar](100) NULL,
[MiddleName] [varchar](100) NULL,
[LastName] [varchar](100) NOT NULL,
[FullName] AS ((([Patient].[LastName]+',') + isnull(' '+[Patient].[FirstName],'')) + isnull(' '+[Patient].[MiddleName],'')),
...
My friend tells me the corresponding "Code First" class looks something like this:
public class Person {
public int ID {get; set;}
public string FirstName {get; set;}
public string MiddleName {get; set;}
public string LastName {get; set;}
public string FullName {get; set;}
...
}
The answer to this question explains the problem and offers a solution.
Design issues
Everyone looking at this wonders why there is a computed column for FullName and, secondarily, why this property is exposed to the client.
Let's just assume there is a good reason for the computed column, a good reason for the model to get the value from the table instead of calculating the value itself, and a good reason to send it to the client rather than have the client calculate it. Here's what he told me about that;
"We need to include the FullName in queries"
Life works out this way sometimes.
Consequences
Notice that the FullName property has a public setter. The EF metadata generator for the Person class cannot tell that this is a read-only property. FullName looks just like LastName. The metadata say "this is normal read/write property."
Breeze doesn't see a difference either. The client app may not touch this property, but Breeze has to send a value for it when creating a new Person. Back on the server, the Breeze EFContextProvider thinks it should pass that value along when creating the EF entity. The stage is set for disaster.
What can you do if (a) you can't change the table and (b) you can't change the model's FullName property definition?
A Solution
EF needs your help. You should tell EF that this is actually a database computed property. You could use the EF fluent interface or use the attribute as shown here:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public String FullName { get; set; }
Add this attribute and EF knows this property is read-only. It will generate the appropriate metadata and you can save a new Person cleanly. Omit it and you'll get the exception.
Note that this is only necessary for Code First. If he'd generated the model Database First, EF knows that the column is computed and doesn’t try to set it.
Be aware of a similar issue with store-generated keys. The default for an integer key is "store-generated" but the default for a Guid key is "client generated". If, in your table, the database actually sets the Guid, you must mark the ID property with [DatabaseGenerated(DatabaseGeneratedOption.Identity)]

How to insert ID in EF 4.1

I am trying something with EF 4.1 that should be relatively easy. I have a class like this
class Entity
{
public int Id {get;set;}
public string Name {get;set;}
}
The Id property should be the primary key in the DB and this all works. But when I insert new entities with given IDs EF4.1 ignores the ID and creates a new one. So I would like something like identity_insert?
Greeting,
Martijn
I'm tempted to closed as a duplicate of this question, but it's not clear from the text if you want to have a property that is always created by your code, or just sometimes (as it is in that question)