How to get EF 4.1 RC code-first to use correct foreign key? - many-to-many

I was using CTP5 and switched to RC1. With no changes to the EntityTypeConfiguration, EF is now trying to look something up by the wrong column name. It is using the singular rather than the plural of the column name and I can't figure out where it is getting that idea.
Example: Many-to-many
//User.Roles
//Role.Users
//User EntityTypeConfiguration
this.HasKey(x => x.Id);
this.HasMany(x => x.Roles)
.WithMany().Map(m => {
m.MapLeftKey("Users_Id");
m.MapRightKey("Roles_Id");
m.ToTable("UserRoleLinks");
});
Then I get the error:
Invalid column name 'User_Id'.
Where is it getting "User_Id"? The table Id is "Id"; The join table is explicitly stated as "Users_Id" What changed between CTP5 and RC1 that would have caused this?
UPDATE:
I am using the "modelBuilder.Conventions.Remove<IncludeMetadataConvention>()" is that one not supported anymore? Could this be the problem? I'm not sure what the default behavior is now.
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
modelBuilder.Configurations.Add(new UserConfig());
}

I figured out what I was doing wrong. The short answer is that I needed to define both sides of the many-to-many relationship because each class participates with a reciprocal collection (User.Roles and Role.Users). Apparently that wasn't necessary with CTP5.
See: Many to Many mapping not working - EF 4.1 RC
To stick with my example, here is the correct syntax.
this.HasMany(x => x.Roles)
.WithMany(r => r.Users).Map(m => {
m.MapLeftKey("Users_Id");
m.MapRightKey("Roles_Id");
m.ToTable("UserRoleLinks");
});
There are a couple pitfalls which obscured the simple solution for me.
1) Only define the relationship once. I was defining the many-to-many relationship from both perspectives in different EntityTypeConfiguration<T> classes, which is not necessary and brings its own errors.
2) Don't mix up the fields you use for the MapLeftKey and MapRightKey. The order is intuitive but I am guessing it is easily something that could get mixed up through copy/paste and what-not.

The Foreign Key naming convention changed in EF 4.1 RC.
The problem is basically that EF now expects the FK to be called User_ID (singular), and the RC provides no ability to configure custom conventions.
If EF recreated the database for you, just change your mappings to User_Id. If you're stuck with a production database I'd recommend using sp_rename to rename the Foreign Keys in your database.
This answer (gotten from a question of mine, see below) worked for me painlessly and seamlessly on a production database.
Useful references
A question of mine about EF 4.1 RC
naming conventions:
EF 4.1 messing things up. Has FK naming strategy changed?.
For further reference, here's a list
of changes in
RC.

Related

SQLModel in Fastapi using __table_args__ is unable to create tables for unit testing [duplicate]

I have a Pylons project and a SQLAlchemy model that implements schema qualified tables:
class Hockey(Base):
__tablename__ = "hockey"
__table_args__ = {'schema':'winter'}
hockey_id = sa.Column(sa.types.Integer, sa.Sequence('score_id_seq', optional=True), primary_key=True)
baseball_id = sa.Column(sa.types.Integer, sa.ForeignKey('summer.baseball.baseball_id'))
This code works great with Postgresql but fails when using SQLite on table and foreign key names (due to SQLite's lack of schema support)
sqlalchemy.exc.OperationalError: (OperationalError) unknown database "winter" 'PRAGMA "winter".table_info("hockey")' ()
I'd like to continue using SQLite for dev and testing.
Is there a way of have this fail gracefully on SQLite?
I'd like to continue using SQLite for
dev and testing.
Is there a way of have this fail
gracefully on SQLite?
It's hard to know where to start with that kind of question. So . . .
Stop it. Just stop it.
There are some developers who don't have the luxury of developing on their target platform. Their life is a hard one--moving code (and sometimes compilers) from one environment to the other, debugging twice (sometimes having to debug remotely on the target platform), gradually coming to an awareness that the gnawing in their gut is actually the start of an ulcer.
Install PostgreSQL.
When you can use the same database environment for development, testing, and deployment, you should.
Not to mention the QA team. Why on earth are they testing stuff they're not going to ship? If you're deploying on PostgreSQL, assure the quality of your work on PostgreSQL.
Seriously.
I'm not sure if this works with foreign keys, but someone could try to use SQLAlchemy's Multi-Tenancy Schema Translation for Table objects. It worked for me but I have used custom primaryjoin and secondaryjoinexpressions in combination with composite primary keys.
The schema translation map can be passed directly to the engine creator:
...
if dialect == "sqlite":
url = lambda: "sqlite:///:memory:"
execution_options={"schema_translate_map": {"winter": None, "summer": None}}
else:
url = lambda: f"postgresql://{user}:{pass}#{host}:{port}/{name}"
execution_options=None
engine = create_engine(url(), execution_options=execution_options)
...
Here is the doc for create_engine. There is a another question on so which might be related in that regard.
But one might get colliding table names all schema names are mapped to None.
I'm just a beginner myself, and I haven't used Pylons, but...
I notice that you are combining the table and the associated class together. How about if you separate them?
import sqlalchemy as sa
meta = sa.MetaData('sqlite:///tutorial.sqlite')
schema = None
hockey_table = sa.Table('hockey', meta,
sa.Column('score_id', sa.types.Integer, sa.Sequence('score_id_seq', optional=True), primary_key=True),
sa.Column('baseball_id', sa.types.Integer, sa.ForeignKey('summer.baseball.baseball_id')),
schema = schema,
)
meta.create_all()
Then you could create a separate
class Hockey(Object):
...
and
mapper(Hockey, hockey_table)
Then just set schema above = None everywhere if you are using sqlite, and the value(s) you want otherwise.
You don't have a working example, so the example above isn't a working one either. However, as other people have pointed out, trying to maintain portability across databases is in the end a losing game. I'd add a +1 to the people suggesting you just use PostgreSQL everywhere.
HTH, Regards.
I know this is a 10+ year old question, but I ran into the same problem recently: Postgres in production and sqlite in development.
The solution was to register an event listener for when the engine calls the "connect" method.
#sqlalchemy.event.listens_for(engine, "connect")
def connect(dbapi_connection, connection_record):
dbapi_connection.execute('ATTACH "your_data_base_name.db" AS "schema_name"')
Using ATTACH statement only once will not work, because it affects only a single connection. This is why we need the event listener, to make the ATTACH statement over all connections.

How to call MySQL stored procedure from ASP.NET Core 3.1 MySql.Data.EntityFrameworkCore

I have a stored procedure in Mysql that returns a table.
Using of old methods like _context.database.SqlQuery doesn't work anymore.
The _context.database.Execute* only contains methods that returns number of affected rows.
In my scenario I'm using scaffolding and can't create database objects from my code, but I can create classes.
The following code (and/or similar tries with Set or Query that is obsolete)
_context.Set<MyModel>().FromSql("CALL My_USP({0});", parametervalue).ToList<MyModel>();
returns an error about that the model is not in the _context because I'm scaffolding and MyModel is a class from my Models.
I'm totally lost with this and all help I can find in S.O. or Google are about EF6, that doesn't work in my case, the libraries are different.
Any workaround will be appreciated also, if this is not possible to do.
I got a solution but I will mark as answer someone that works without the old ADO.NET or change my dbcontext like this one, because will fail the next time I will do a scaffolding.
Add to protected override void OnModelCreating(ModelBuilder modelBuilder) in the context file:
modelBuilder.Entity<MyModel>().HasNoKey();
and then call:
_context.Set<MyModel>().FromSqlRaw("CALL My_USP({0});", parametervalue).ToList<MyModel>();

Yii model relationship, how is it important?

It is my first time to use yii and unlike my old programming style, i notice that it use relationship automatically in its model.
public function relations()
{
return array(
'author'=>array(self::BELONGS_TO, 'User', 'author_id'),
'categories'=>array(self::MANY_MANY, 'Category',
'tbl_post_category(post_id, category_id)'),
);
}
I'm not used in doing this MySQL relationship. my old programming habit is connecting/manipulating the data to the php program itself.. To clarify my question, is this yii model relationship important? if i dont use this method, will i encounter problems?
Yii relations are very useful and if you work with it you will see that it will make you do less coding and make your code more readable.
while it is so much used in Yii applications, if you don't use relations, you won't get into any trouble, it is supposed to help you code and develop faster.
like if you looked at Yii blog, you have relation between Post model and Comments model, and you could go like this:
$post = Post::model()->findByPk( $id ); // find one post
$allCommentsRelated = $post->comments; // just one line for all search query and instanciating models
BTW in relations, there are two type of loading:
lazy loading (this is default mechanism)
eager loading
you have to know your scenario, and choose one that suites that scenario best

Entity Framework: Auto-updating foreign key when setting a new object reference

I am porting an existing application from Linq to SQL to Entity Framework 4 (default code generation).
One difference I noticed between the two is that a foreign key property is not updated when resetting the object reference. Now I need to decide how to deal with this.
For example supposing you have two entity types, Company and Employee. One Company has many Employees.
In Linq To SQL, setting the company also sets the company id:
var company=new Company(ID=1);
var employee=new Employee();
Debug.Assert(employee.CompanyID==0);
employee.Company=company;
Debug.Assert(employee.CompanyID==1); //Works fine!
In Entity Framework (and without using any code template customization) this does not work:
var company=new Company(ID=1);
var employee=new Employee();
Debug.Assert(employee.CompanyID==0);
employee.Company=company;
Debug.Assert(employee.CompanyID==1); //Throws, since CompanyID was not updated!
How can I make EF behave the same way as LinqToSQL? I had a look at the default code generation T4 template, but I could not figure out how to make the necessary changes. It seems like a one-liner should do the trick, but I could not figure out how to get the ID property for a given reference.
From what I can see in the default T4 template, the foreign key properties of entities are not directly linked to the entity reference associated with the key.
Theres a couples to approach to your issue regarding migration from Linq to SQL to EF4. One of them would be to register to the AssociationChanged event of your associations so that it updates your field automatically. In your context, one approach could be something like like this :
// Extends Employee entity
public partial class Employee
{
private void CompanyChanged(Object sender, CollectionChangeEventArgs e)
{
// Apply reactive changes; aka set CompanyID
// here
}
// Create a default constructor that registers your event handler
public Employee()
{
this.CompanyReference.AssociationChanged += CompanyChanged;
}
}
Personally, if you want to limit the maintenance required to maintain this sort of logic, I'd suggest changing your T4 template (either change it yourself or find one) so that it sets the CompanyId when Company is changed as shown previously.
Gil Fink wrote a pretty good introdution to T4 templates with EF4, and you can look up Scott Hanselman wrapped a good bunch of useful links and ressources to work with T4 templates.
On a last note, unless I'm mistaken, accessing foreign keys directly as propeties of an entity is something new from EF3.5 to 4. In 3.5, only way you could access it was through the associated entity (Employee.Company.CompanyID). I believe the feature was added in EF4 so that you didn't have to load associations (using "include") in order to get the foreign key when selecting from the data store.
Perhaps EF's take on this would be, if you got the association, go through the association to get the ID, first and foremost. But that's just speculation as I got no quotes to back it up.
[EDIT 2010-06-16]:
After a quick readthrough and analysis of the edmx xml elements, I found one called ReferentialConstraint which appears to contain foreign key fields to a specfic FK_Relation.
Heres the code snippet to modify inside a default T4 edmx template, section Write Navigation Properties. (Template_RegionNavigationProperties), around line 388 of an unmodified template. Try to ignore the horrible formatting...
<#=code.SpaceAfter(NewModifier(navProperty))#><#=Accessibility.ForProperty(navProperty)#> <#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#> <#=code.Escape(navProperty)#>
{
<#=code.SpaceAfter(Accessibility.ForGetter(navProperty))#>get
{
return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>").Value;
}
<#=code.SpaceAfter(Accessibility.ForSetter(navProperty))#>set
{
// edit begins here
if(value != null)
{
// Automatically sets the foreign key attributes according to linked entity
<#
AssociationType association = GetSourceSchemaTypes<AssociationType>().FirstOrDefault(_ => _.FullName == navProperty.RelationshipType.FullName);
foreach(var cons in association.ReferentialConstraints)
{
foreach(var metadataProperty in cons.FromProperties)
{
#>
this.<#=metadataProperty.Name#> = value.<#=metadataProperty.Name#>;
//this._<#=metadataProperty.Name#> = value._<#=metadataProperty.Name#>; // use private field to bypass the OnChanged events, property validation and the likes..
<#
}
}
#>
}
else
{
// what usually happens in Linq-to-SQL when an association is set to null
// here
}
// edit ends here
((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<<#=MultiSchemaEscape(navProperty.ToEndMember.GetEntityType(), code)#>>("<#=navProperty.RelationshipType.FullName#>", "<#=navProperty.ToEndMember.Name#>").Value = value;
}
}
I roughly tested it, but it's a given that theres some validation and such missing. Perhaps it could give you a tip towards a solution regardless.
Thanks for this solution. I've enhanced it (does not depend on specific naming conventions anymore) and encluded in a fix that also fixes an other issue with the Entity Framework template.
Check here for my solution and fixed code generation template

Linq to Sql inheritance mapping to multiple tables

I am having trouble with inheritance mapping in Linq to Sql. I am using MSDN as a reference and as a basis it sounds good. However the example it gives is a single table inheritance mapping. However, I am trying to do multiple table inheritance to save on table space. Is this possible? So far I have:
[Table(Name="writing_objs")]
[InheritanceMapping(Code="T",Type=typeof(ObjectTypeA), IsDefault=true)] // Only default because a default is required
[InheritanceMapping(Code="N",Type=typeof(ObjectTypeb))]
public abstract class WritingObject
{
/* ... */
[Column(Name="obj_tp", IsDiscriminator=true)]
[StringLength(1)]
public string ObjectType { get; set; }
}
I then have the different object types defined like so:
[Table(Name="obj_type_a")]
public class ObjectTypeA: WritingObject
{
/* Object Type A fields */
}
The issue seems to be that I am defining a table attribute in the 2nd type, as I get the following exception:
The inheritance subtype 'ObjectTypeA' is also declared as a root type.
Is it possible to keep these fields in separate tables with Linq to Sql or am I going to have to consolidate them all into a single table? Is it necessarily bad to have some extra fields in one table as long as there aren't too many (some object types might even be able to share some fields)?
Linq to SQL does not support multiple-table inheritance using a discriminator, even though that is the best design in many cases (it's the most normalized).
You'll have to implement it using associations instead. If you use a mapping layer that converts it to an inheritance-based domain model, it will be easier to manage at higher layers.
Well I know this problem has already been resolved, but as I just encountered the same issue, I'd like to share what I did :
Just remove the [Table] attribute from your inherited classes. And it's quite logical, because we define in the generic classes a way to store all subtypes (with the discriminatory attrbute).
Maybe this will help someone in the future.