How do a rename a domain class while reverse engineering or after reverse engineering.
i generated class using reverse engineering in Groovy and Grails.
the domain class name was AgentTable. I want to rename it as Agent. When i renamed the domain class using IntelliJ (right click - refactor - rename), it renamed the AgentTable to Agent whereever it was used. but when i start the server (run the app), giving error
"nested exception is org.hibernate.HibernateException: Missing table: agent"
I have to do this for few domain class. is it anyway i can give an alternative name while reverse engineering the domain classes.
or after domain class was created how do i rename it without this error.
Look into your database the name of the table it created for the agent. Once you know the name of the table add the following in your new domain
static mapping = {
table "table-name-here"
}
While it works I would not recommend #elixir 's approach.
In my opinion the mapping is not supposed to be used for renames. This is also how I understand the official documentation.
In the example they use it to map Person onto the 'people' table, not because of a rename but because of a semantic reason. Tables are typically named after the plural form. Here is a nice answer on another question regarding this. In the project I am working on the domain object 'User' is mapped to the table 'users'. You can not use the table name 'user' as it is an SQL statement.
Assumptions and clarifications:
In my experience Grails maps the domain name to the table name after these rules (example domain name 'MyExampleDomain':
separate the domain name by capital letters (My Example Domain)
lower case all (my example domain)
replace spaces with underlines (my_example_domain)
Following this your Domain Class 'AgentTable' has a table 'agent_table' in your respective database. After your rename Grails even tells you what it wants:
nested exception is org.hibernate.HibernateException: Missing table: agent
It wants to look up values in a table called 'agent' but it can not find it. The refactor function of IntelliJ does not rename the functions, so it will miss out on the database.
Luckily we know exactly what values it wants - the values previously found in 'agent_table'.
So why create this confusion with remapping domains and table names when we could just rename the table and be done with it?
The solution:
Execute an SQL script like this on your database:
ALTER TABLE <old_domain_name> RENAME TO <new_domain_name>;
The names are of course in their "table-form".
This simply renames your table to match the expected format in Grails. When restarting everything should be fine.
However you do not need to use rename. You could also create a whole new table, build it the way the domain objects wants it to be and then migrate the data. See section 'Problems with this approach' for information on when to use what.
Problems with this approach:
As always, tinkering with information a program depends on (and even generated itself) will often have some dire consequences if you aren't careful.
For example we have to pay attention to keys. If your domain object has a relation to other objects it will hold them in the table via foreign keys. Depending on how you chose to migrate the information in the table you might have deleted these foreign keys connections. You will have to add them via a separate SQL statement. When you choose to recreate the table this will happen for sure. Renaming it should keep the keys.
Another one are column names. If you choose to rename attributes you will also have to rename the columns via SQL. You will also have to remember the foreign keys other tables might have on the table you are renaming. RENAME did this automatically for me, but you should double check.
Why you should still stick with this approach:
Remapping domain objects to the tables with old names is bound to create code smell and confusion. Do you really want to remember these mappings in your head? And more importantly: do you really expect other people to have to work with this?
The best case is if people can't even tell if this object has ever had a different name and changing the database is the best way I know to achieve this.
Related
This is probably the single biggest time-waster I have: I must have wasted cumulative days trying to get round it.
I'm using Visual Studio 2015 and ASP.NET MVC 5, but don't think this is important - I've had this problem in other versions. I accept that it's based on my ignorance.
I've got a reasonably complicated SQL Server database, and am using database-first model generation. To keep things manageable, I've got about 20 different models, each containing tables on a particular theme.
So let's say I want to generate a model to contain tables to do with the maps in my database. First thing to do is to add a new entity model database:
I want to call my model webMap:
I choose to generate the model from my database:
I've got a perfectly good connection string to the database in my web.config file, so I use that and choose not to save this:
I then choose the tables for which I want to generate classes, and these options:
What happens then is that it doesn't recognise the new database context:
The reason is (I think) in this file:
This has created a class named after a connection string:
If I change the partial class and constructor name like this:
then it solves the problem - until I next need to update the database.
Please forgive my ignorance about what's going on. Although I like what entity frameworks do, I find the opacity of what's going on hard to work with. Could any kind person tell me what I'm doing wrong, without delving into T4 transformations? I've tried cleaning my solution and running custom tools, by the way. Thank you!
Open the edmx file in the designer and click somewhere inside to select the conceptual model in the Properties window. Now look at Entity Container Name property. The value should be Entities - I think derived from your connection string name and no way to be specified during the Add wizard steps.
Simply change it to the desired name of the context (like webMap), save/build and you are done.
But make sure the Namespace and Entity Container Name property values are different.
Many thanks to Ivan and garret for their answers. I've collated the information and put here a procedure which worked for me. I don't claim to understand fully what's going on (but surely the point of a framework like this is that I shouldn't need to?).
Here's how I managed to create my model. There are 6 steps. I don't know which of them can be omitted, but following them all solved my problem.
Step 1 - Delete any existing models referencing tblMap
I found that I had inadvertently created another model. Doing a global search for (in my case) webMap can help find if you are in the same position.
Step 2 - clear the web.config file connection strings
I don't understand why, but it appears that the connection strings in your web.config file show up as conflicting names in code. So I did a search for webMap in my web.config file and deleted all connection strings containing it. I think this is the step that I had previously omitted.
Step 3 - Clean and rebuild the solution
I cleaned the solution (no idea if this was necessary), then rebuilt it to ensure that the only errors I had left were in my code referencing the webMap database context which no longer existed.
Step 4 - Follow the steps to add an ADO entity model
But ... call the item name in the first screen something like webMapModel, the connection string something like webMapEntities (and choose to save this in the web.config file) and the namespace something like webMapNamespace. Note that none of these is the webMap name I want to end up with.
Step 5 - Change the entity container name
Double-click on the model .edmx file which has been created to open it (this might not be necessary - it may be open already). Click on the white background of the model to deselect any entities. Press F4 to bring up properties.
Change the entity container name to webMap as shown above.
Step 6 - Rebuild your solution
At this point all my errors disappeared!
Name of Your context, should be different than namespace.
Try to use this configuration:
And in next screen:
And yes, it will add next connection string to web.config, but it's ok.
I am writing an application based on an existing database. I have two tables, a server table and a support table (people who support the specified server). These tables can have a many to many relationship, and as such I cannot maintain a foreign key within one of the tables pointing to another.
The solution that the person who designed the schema came up with was to add a third table, a server support junction, that has just two columns - ServerID and SupportID, both foreign keys pointing to their respective table.
When I import this database schema into Entity Framework, it gives me the following warning:
Warning 2 Error 6002: The
table/view 'dbo.Server_Support_Junction' does
not have a primary key defined. The key has been inferred and the definition
was created as a read-only table/view.
As such, the table does not appear in the edmx model and it does not create a class for the table.
As part of the application, I would like the DBA to be able to delete a server or a support (they leave the company/no longer support a certain server/etc). Is entity framework smart enough to see that this table is purely relational and will remove any connections when a support or server is deleted? Or must this be done explicitly?
If it must be done explicitly, what is a workaround for this? I tried adding a primary key called RelationID to the table, but it yelled at me saying that the primary key was not mapped or something.
Gert Arnold helped to find the solution. First, a primary key was added to the table consisting of both the Foreign keys, the SQL was:
ALTER TABLE dbo.Server_Support_Junction
ADD CONSTRAINT pk_ServerSupportJunc PRIMARY KEY (ServerID, SupportID)
I then updated the model by opening the edmx, right clicking on the blank space -> update model from database -> refresh -> finish.
To delete the relationship in the controller, the code was as follows:
Support support = db.Support.Find(id);
support.Servers.Clear();
db.Support.Remove(support);
db.SaveChanges();
Obviously you should do some error checking to make sure the entity was actually found, but that's the gist of it!
Special thanks to Gert Arnold!
I have a following domains
User (in database called usermanagement) and
Account (in another database xyz)
Its an old system so i cannot really change the architecture of the system. I have been assigned task to implement a system that a certain users can only access certain accounts. This is a classic case of many-to-many relationship but the problem lies in the fact that these two domains are in two different databases. I googled if that was possible but i realized that it was not possible. So I now am thinking of creating a custom join table to store info on which user are allowed access to which accounts. The table can have two columns 'accountId' and 'userId'. So for this, do i have to create a new domain in grails or is there any cleaver way of doing this ?
Thanks in advance.
If you create joinTable in which DB you are going to create it and how you are going handle updates in main (Account,User) tables and ceep your join table up2date ?
I think (for this case) you don't need join table, you need handle business logic in application level.
You cane have 2 Domain classes each one pointed to different dataSource(DataBase).
http://grails.org/doc/latest/guide/conf.html#multipleDatasources
As I searched for solution of this, I did not find any sustainable solutions. I eventually narrowed down the probable solutions to two:
1. Create a domain table (only) using sql, some sort of patch and use hard-coded queries in grails to write and access data to and from the table.
2. Create a domain class like AccountUser having properties clientId and userId
I choose the 2nd option, I wrote some additional methods and created a service to return user and client instance and I am done ! Anyways, thanks guys.
If the databases are "visible" to each other (on the same server or there is a db link between them), you should be able to map the domain classes using the fully qualified table names ('schema.tablename') in the mapping closure.
psuedocode:
class User {
static mapping = {
table "usermanagement.user"
}
static hasMany = [Account:accounts]
}
class Account {
static mapping = {
table "xyz.account"
}
}
http://grails.org/doc/latest/guide/GORM.html#tableAndColumnNames
I am learning code first and I have project to be used with an existing database.
I am a bit confused of what I meant to be doing.I will explain:
Do I need to create an entityconfiguration for each table in my existing database?
Within this EntityConfiguration for each table do I need to create foreign key relationships?
Do I need to do a ToTable for each table in my existing database?
Is there any free tool "codeplex" that pointing to an existing db will generate this codeFirst stuff?
I have seem few blogs about "EF Code first with existing db" but I am not sure or was not clear to me If Need to create this stuff or I will be getting strange errors like "MyColumn_MyColum" basically as if codeFirst is trying to build some FKs or something.
can somebody clarify?
thanks a lot. I know there are few questions but if you can answer 01 or 2 that would be fine.
thanks again
If you want the code to be generated for you use database-first approach with DbContext API. Simply create EDMX file from your database and let DbContext Generator template generate all entities and context for you.
DbContext Fluent API is mainly targeted to the code-first development approach where EF will created database for you from the code you provided. It can be used with existing database but it requires much more skills and understanding of mapping wich EF can provide to you.
Generally:
You don't need to provide EntityConfiguration for each table if you follow some naming conventions (entity name is singular form of table name, all properties have the same name, primary key in table and entity is named as Id or EntityNameId, etc.).
You don't need to define relationships manually if you follow conventions with exposing navigation properties and possibly also foreign key properties. The issue can be naming of many-to-many keys and junction tables.
ToTable is needed only if your entity does not follow naming convention or if you map some advance inheritance or splitting.
EF uses a lot of default conventions which drive how the names should be defined. Conventions can be removed.
You will not do anything wrong if you define EntityConfiguration for each table - it will at least allow you learning what is needed and your mapping will be explicit / self documented.
I have many legacy databases from which I need to pull raw data. Each of the tables in the database have arbitrary names, and an arbitrary collection of fields. I have been getting access to these fields with the following class:
class Frt < ActiveRecord::Base
establish_connection :legacy
set_primary_key "point"
end
When I reach the point in my code where I know the table name, I can call:
Frt.set_table_name "table"
t = Frt.find_by_sql("blah")
something = t.field_name + t.other_field_name
etc...
The problem is that I've realized that this locks the accessible field names to whatever table I select first. If I try to change the table with another call to the `set_table_name' method, it changes the attribute for the class, but any new instances will still have the same set of fields as the first one. So far, in my app, I've not needing anything else, but I'm expanding the program in a way in which I know it will bite me in the butt down the road.
I've tried `Frt.send :set_table_name "new_table"', hoping that it would cause ActiveRecord to do it's magic again. It doesn't.
Can anyone suggest how I might be able to keep the convenience of ActiveRecord, but get it to dynamically remap its fields for whatever table I need loaded?
I've never used it, but Magic Model Generator claims to create models for tables automatically.
Sorry to answer my own post, but I guess I didn't explain it very well. In case someone else comes along after this, what I needed to do was issue a call to the "Frt.reset_column_information" method. I was revisiting this issue, and just dumped all the methods on the ActiveRecord class, and found that one lurking in the list.
A better way to solve this would be to create a model for each legacy table you need to interact with - no dynamic table name remapping required, and it works right out of the box.