Entity Framework singularize/pluralize not working as expected - c#

Using EF 6, when we generate the models (dbmx) from our database, we have the checkbox checked that states:
Pluralize or singularize generated object names
However, when the classes are generated, the name of each class is the exact name of the table, and its properties (whether a db type or db set) are the exact name of their respective table as well.
Basically, everything is pluralizing...
public virtual DbSet<Documents> Documents { get; set; } // Shoud be of type 'Document'
public virtual Images Images { get; set; } // should be of type 'Image', and named 'Image' as well
What am I missing here? Seems like EF just isn't naming things correctly.
Edit
I've tested this with singular and plural table names. As mentioned above, the generated code mimics exactly what the table names are. If the table name is Documents, then the type generated in C# is Documents... The type should be Document though.
In another solution, the generated code takes the plural table name Documents, and generates a type called Document out of it. THIS is the expected behavior for our new solution... but it's not working that way for some reason.

Related

A correct way to alter Cassandra table via C#

My issue is in the next.
I have the next simple model in my code:
public class Client
{
public Guid Id { get; set; }
public string Name { get; set; }
}
I defined a mapping for it:
public class CustomMappings : Mappings
{
public CustomMappings()
{
For<Client>().TableName("clients")
.PartitionKey(x => x.Id);
}
}
I created the table via Table<TEntity>.CreateIfNotExist() method:
var table = new Table<Client>(session);
table.CreateIfNotExists();
And I can insert my data by the next way:
IMapper mapper = new Mapper(session);
var client = new Client
{
Id = Guid.NewGuid(),
Name = "John Smith"
};
await mapper.UpdateAsync(client);
After this, I've changed my model by adding a new property:
public class Client
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
I need to alter this table, because I want to add surname column to it.
Of course, I have the exception without it when I try to insert a value:
Cassandra.InvalidQueryException: Undefined column name surname
at Cassandra.Requests.PrepareHandler.Prepare(PrepareRequest request, IInternalSession session, Dictionary`2 triedHosts)
at Cassandra.Requests.PrepareHandler.Prepare(IInternalSession session, Serializer serializer, PrepareRequest request)
at Cassandra.Session.PrepareAsync(String query, IDictionary`2 customPayload)
at Cassandra.Mapping.Statements.StatementFactory.GetStatementAsync(ISession session, Cql cql, Nullable`1 forceNoPrepare)
at Cassandra.Mapping.Mapper.ExecuteAsync(Cql cql)
But class Cassandra.Data.Linq.Table<TEntity> does not contain neither nor .AlterOrCreate() nor .Alter() methods. Also, we don't have .GetAlter() method in Cassandra.Mapping.Statements.CqlGenerator.
Which way is more appropriate to solve this problem? I have two assumptions (besides creating a pull request with needed methods to datastax csharp driver repository on github :)).
To alter tables via cql script in .cql file which will be executed in c# code.
To create a new table after each changes of a model and migrate old data to it.
I'm a newbee in Cassandra and I have suspicions that needed method does not exist in the library for good reason. Maybe, are there any problems with consistency after altering because Cassandra is distributed database?
Changes in the Cassandra's schema should be done very accurately - you're correct about distributed nature of it, and when making changes you need to take into account. Usually it's recommended to make changes via only one node, and after execution of any DDL statement (create/drop/alter) you need to check for schema agreement (for example, via method CheckSchemaAgreementAsync of Metadata class), and don't execute next statement until schema is in agreement.
Talking about changes themselves - I'm not sure that C# driver is able to automatically generate the changes for schema, but you can execute the changes as CQL commands, as described in documentation (please read carefully about limitations!). The changes in schema could be separated into 2 groups:
That could be applied to table without need to migrate the data
That will require creation of new table with desired structure, and migration of data.
In the first group we can do following (maybe not a full list):
Add a new regular column to table
Drop a regular column from table
Rename the clustering column
Second group includes everything else:
Changing the primary key - adding or removing columns to/from it
Renaming of non-clustering columns
Changing the type of the column (it's really recommended to create completely new column with required type, copy data, and then drop original column - it's not recommended to use the same name with different type, as it could make your data inaccessible)
Data migration could be done by different tools, and it may depend on the specific requirements, like, type change, etc. But it's a different story.

Table name in code first approach is automatically changing

I have created a class name History with required columns and used the package manager console to update the database the thing that I have noticed is that the table in database created is Histories.
Wanted to know that how History to Histories got created.
Another table with Transactions created which is correctly created.
All the table name ending with y alphabets gets converted to ies would to understand where is such kind of logic written.
If you add the annotation '[Table("YourTableName")]' to your table class, it should create your table in the db as what you named it and not "YourTableNames".
Like this:
[Table("MyTable")]
public class MyTable
Also, in your db context (i.e., ApplicationDbContext), you would usually pluralize the dbsets with type of tablename tablenames. As in:
public DbSet<TableName> TableNames { get; set; }
As mentioned in the comments, it's part of the conventions. Not sure if that explains it, but it should be a start.

Dynamic Property Binding in EF?

Apparently, the same columns value-type differs across environments for the same database entity (table) & they refuse to update to a common type - don't ask why!
I am using Entity Framework (version 6.1.3) alongside a Unit of Work for data-access. And, as you can guess, I am getting errors because the DEV & the QA database definitions do not match for the same column.
THE GOOD NEWS:
We do not save into these particular tables - we only query those particular tables.
SAMPLE MODEL:
There are obviously more columns than this.
public partial class Transactions
{
[Key]
public int TransactionId { get; set; }
public float Amount { get; set; } //<-- This type differs between database environments
}
MY QUESTION:
Is there a way to dynamically bind the value for a column in Entity Framework?
Or, can I treat it as a dynamic under-the-hood...and transform it to an expected type which is constant to my model?
OPTIMALLY - AND TO BE CLEAR:
I would like to define the property concretely, and have Entity Framework "convert" from the unknown type & into the concrete type - but under-the-hood.
Any help is appreciated.
If the types of the columns are compatible (i.e. are all numbers) you can have a common type on the class then disable model checking (and migration). This solution could work on some DBMSs and not on some Others (depends on the provider).
You can write a view with cast and map it in your model (and not the table).
You can write a direct query with EF (official docs https://msdn.microsoft.com/en-us/data/jj592907.aspx similar to Dapper solution with same advantages and defects, in your case lazy load won't work).

EF6 ignoring [Table] and [Column] in entity classes

I used EF6 Database First tools to generate C# classes for 2 tables from my database, then (as advised in the blog post that helped me through the steps to do that) copied the resulting .cs files into a new project. I made a few edits to the classes to support sensible names in my C# code. Here's a snippet of one of the classes with "LongTableName" replacing a strangely long name used in the database.
namespace RidesData
{
[Table("LongTableName")]
public partial class PhoneData
{
[Key]
[Column("LongTableNameID")]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Column("LongTableNameAccountID")]
public int AccountID { get; set; }
// more fields
}
}
I am not in control of the table names, nor the fact that the many of the column names have the table name as prefixes. But the Code First ideas in EF6 should, I thought, let me use reasonable class and field names despite that. (The Database First code generator did a good job of adding code to OnModelCreating to specify that none of the columns corresponding to C# string data used Unicode.)
My model (generated by the EF6 tools and that inherits from DbContext) includes (after some renaming by me)
public virtual DbSet<PhoneData> PhoneRecs { get; set; }
and I thought all would be fine when I created an instance of PhoneData, populated it, and did
Model.PhoneRecs.Add(phoneData);
but the first thing that happened when I ran the code -- well before any call to SaveChanges() -- was that EF generated CREATE TABLE statements for the two tables; the table corresponding to the snippet above was named PhoneDatas (not using the specified table name) and the column names were the same as the field names in the class (not what was specified in the Column(...) attributes).
Of course the table I had specified did not need to be created. EF just had to grok that I wanted to use the table and column names I had specified via attributes.
I did not expect this failure of explicit Code First attributes. Does anyone have a clue why this isn't doing what I want, or how to fix it? (Do I have to do something to specify the table & column names in OnModelCreating as well as -- or instead of -- the attributes?)
Note that the project that I copied these classes into had never "seen" the database before. There are no vestiges of any "models" left over from tooling having looked at the database. Also, I hope it does not matter that I've tried to keep things on .Net 4.0 (avoiding going to 4.5 in this code).
Any assistance would be appreciated.
I'm not a big fan of DataAnotations either. Use EntityTypeConfiguration. It gives you the naming flexibility I think you are looking for.
Example.
public class PhoneData
{
public int ID {get;set;}
public string SomeProperty {get;set;}
}
public class PhoneDataMap : EntityTypeConfiguration<PhoneData>
{
public PhoneDataMap()
{
ToTable("WhatEverYou_Want_to_call_this");
HasKey(m => m.Id);
Property(m => m.SomeProperty).HasColumnName("whatever").IsRequired();
//etc.
}
}
Then in your on ModelCreating you add
modelBuilder.Configuration.Add(new PhoneDataMap());
On a side note, if you are having trouble with pluralization of your table names you can add this to OnModelCreating as well
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

MVC4 code first force database column name

I have the following problem: I have a hierarchy of entities that uses inheritance. I have a two identical fields( the name and type is the same ) in two of the sub-entities. When I try to "Update-Database -Force" on the project EF5 complains that there are there is already a column with name X.
The way EF5 generates the tables is that it actually generates single table and puts there all the fields of the base entity plus the all the fields of the derived entities.
Is there a way to force a different database column name from the property name.
Are there any other solutions( I know it might be architectural problem to duplicate data but making this common will introduce more complex database hierarchy that I don't want to use ).
Thanks:)
This can be done in one of two ways, either using Fluent API or property attributes on your class properties.
[Column("ColumnName")]
public string PropertyName
{
get;
set;
}
See MSDN - ColumnAttribute Class for more details on the column attribute.
Otherwise, use Fluent API. Within your context class-
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<YourClass>().Property(yc => yc.PropertyName).HasColumnName("ColumnName");
See MSDN - HasColumnName extension method for more on this method.
The article linked by Baximilian will be useful in learning more about this.
If I understand you correctly, you need to change column name in DB for field, so you can use ColumnAttribute.
You can find more information here

Categories