I can quite easily generate a model from MySQL/MariaDB view with Gii, but when I try to generate CRUD, than I recieve the following error message:
The table associated with frontend\models\MyModel must have primary key(s).
See also the discussion in Yii Framework Forum.
The solution is:
add an ID in the view, e.g. using the CONCAT function,
overwrite the method primaryKey in the generated model.
Here is the code:
public static function primaryKey()
{
return array('view_id');
}
It is not a standard solution and should be used carefully. Yii does not officially support using active record with views, because different DBMS have different view specs and they usually don't support DB write (2).
Working on yii2,
There was issue with primary Key, so I search to add primary key in VIEW TABLE but I can't because -
Create view with primary key?
Adding in a primary key to an SQL view
Then moved to create CRUD on VIEW Table. I view many articles like-
http://www.yiiframework.com/forum/index.php/topic/9544-create-a-model-and-crud-from-mysql-view-instead-of-table/
https://code.google.com/archive/p/yii/issues/1274#c0
so finally,
public static function primaryKey()
{
return array('my_view_id');
}
Worked for me.
Related
I've been messing with the Design view of my DBML class for hours now. I have one class, call it A, that has a 1 to many relationship with B, C, D, and E. In the generated code I can see that Class A has generated
private EntitySet<BB> _bb;
private EntitySet<CC> _cc;
private EntitySet<EE> _ee;
But it hasn't generated one for D. Finally for giggles I added a primary key to D; all the other classes had one except for D; and NOW it's generating a EntitySet _dd. But why is this? I don't need that table to have a specified primary key.
I assume you are using LINQ to SQL due to the .dbml files. LINQ to SQL (and Entity Framework to some degree) struggle with tables that do not contain primary keys. Specifically, the table needs a primary key to implement INotifyPropertyChanged (the interface that tracks changes for a specific identity... how can an entity be tracked if it does not have a primary key?). A good example of why this is needed can be found here.
https://social.msdn.microsoft.com/Forums/en-US/f3b216d2-fa06-49a1-a901-11702e80b38c/linq-to-sql-table-doesnt-have-primary-key?forum=linqtosql
As a follow up, is there a specific reason why the table does not have a primary key? Does it not represent a entity in your data model? If it is a "lookup" table perhaps you can wrap the functionality in a stored procedure and then call the stored procedure via LINQ to SQL.
I am working on a project that is an upgrade of an existing system.
The existing DB structure must be kept intact as there is a system reading the same DB that will be used ontop of the new system.
I am building a new CMS / Management system using a PHP framework that expects so see all DB table autoincrement ID field named simply "id" - I do not want to modify the PHP deal with anything other that "id" as this field name - trust me it will be a massive task.
The existing DB has non standard Autoincrement ID field naming, eg:
"iBmsId" -shcema: i=INT Bms = the name of the table, Id = ID....
Is there anything I can do to the DB itself to make a duplicate of the "iBmsId" column, to create a matched column called simply "id" that has the corresponding INT values? This way my new system will function as expected without having to do a serious re-write, and at the same time still have the existing system able to communicate with the DB?
In this situation you can just use VIEW :)
http://dev.mysql.com/doc/refman/5.0/en/create-view.html
View in dbms is like a virtual table (unless it's materialized). Views add a new abstraction layer which can support independency between how you use db and how it's implemented. It can also increase security for example by hiding some fields or making view readonly.
Notice: In order to add view transparently you can rename origin table and create the View with origin table name. This let's you avoid modifications in existing code.
You can read here how to create updatable and insertable view (which can behave as normal table).
If only one system at a time is modifying the value, then you can use a view:
create view v_table as
select t.*, iBMid as id
from table t;
Presumably, an auto-incremented value is not going to be updated, so this should be safe. However, keep in mind that:
To be more specific, a view is not updatable if it contains any of the following:
. . .
Multiple references to any column of a base table.
This could affect other columns that you might want to treat the same way.
Following on from this question here:Entity Framework Reverse Engineer using Power Tools - No Primary Keys
I've reverse engineered a database using Entity Framework Power Tools Beta 2.
This has created a large number of POCO's and a mappings folder with the entity mappings.
When I attempt to create a controller using the Add Controller Dialog I get the following message box come up:
Unable to retrieve metadata for cruise model. One or more Validation errors were detected during model generation:
\tSystem.Data.Entity.EmdEntityTypes:: cruise table has no key defined. Define the key for this EntityType.
This repeats many times for all the related tables to the original one for which I was trying to create a controller.
The Controller itself is never created and on pressing OK I'm returned to the Add Controller Dialog.
The model in question definitley has a primary key defined in it's mapping file:
// Primary Key
this.HasKey(t => t.cruise_ID);
What am I doing wrong?
How does the controller find the mapping classes?
I've been able to replicate the error your receive, and it's related to trying to create a controller for the Model itself, rather than for the entity type.
The MVC scaffolding is designed to target an entity, then the related context - are you sure you're selecting the right items in the drop down?
In This image:
Your model drop down (Mine shows A (MVCExamples.Models)) should refer to what I assume is your cruise entity.
Your Data Context should be the DbContext that gets created (Mine shows Entities (MVCExamples.Models))
ADD :
using System.ComponentModel.DataAnnotations;
and a primary key to db class is calling'
I'm using phpMyAdmin for my database GUI and it's connecting to Yii Framework on my website.
I wish for my products table for instance, to have a foreign key department_id which is a reference to the id field of my departments table. Unfortunately, I don't currently have the facility to set the foreign key up properly in phpMyAdmin, so department_id is just an indexed field. I cannot change the configuration of phpMyAdmin at the moment so it's stuck like it is without a foreign key and relationship facility.
Is there a way to modify the Models of these tables in Yii so they link? I know there is a relations function inside the Model Class file that holds this information:
return array('department_id' => array(self::BELONGS_TO, 'Departments', 'id'),
Could I not just add something similar to the above? Is there more legwork? Is it now fixed (as in static, not corrected) because of phpMyAdmin?
Cheers
If I'm not mistaken, you don't need to have mySql enforcing foreign key relationships for them to still work in Yii. Setting up FK constraints in mySql ensures proper database integrity, but I don't think Yii actually uses that at runtime.
When initially running yiic (of Gii) to build the project I think it looks at the DB to build the right relations in the Model, but it doesn't use them after that.
Yii then uses this knowledge (from yiic) of the table relationships to make your life easier by providing shortcut methods to access relational data, and to ensure you don't violate mySql constraints and get ugly SQL errors, etc. But you can still use Yii relation logic without the underlying SQL constraints. The only problem will be that if Yii messes up and assigns a non-existing FK or something, your database will not catch this error (your data integrity will be more error prone).
To link your products to departments, just make sure you have a department_id field in the Product (which it sounds like you do). Then add a relation rule like so to Product:
'department' => array(self::BELONGS_TO, 'Department', 'department_id'),
And in your Department model:
'products' => array(self::HAS_MANY, 'Product', 'department_id'),
Now you should be able to use the relation like normal:
$myProductModel->department; // returns the model of the Department referenced
$myDepartmentModel->products; // returns the models of all Products in the department
Good luck, and let me know if I am way off base and it doesn't work for you!
I have an interesting problem and wanted so see if anyone else has seen this. I've created a MVC 2 site using Visual studio 2010 beta 2. I'm using linq to sql data model objects with data annotations.
In my data model objects I'm using [ScaffoldColumn(false)] attribute to exclude the foreign key ID's from rendering to the UI when I use the EditorForModel method. For some reason the UI is rendering the foreign key table name.
e.g. if the foreign key is AccountID, i see the "account".
I wonder if this is a bug in the editorformodel or if I need to use a different/additional data annotation attribute to instruct editorformodel to not render anything.
You Linq to SQL classes will have a property for the foreign key itself (AccountID) as well as an EntitySet property for the related records in the Accounts table. If you open up the auto-generated designer.cs file under your linq to sql dbml - you can view all the properties of each class. I think by default the templated helpers are only supposed to generate an editor for the first level of properties. There is a "deep-dive" option that will extend the generated editor to more levels of properties. Check out Brad Wilson's blog on the subject (near the end of the post).
In general, trying to throw your auto-generated Linq to SQL classes into your View or annotate them with attributes gets pretty hairy. It might be worth checking into strongly typed view models where you could specify only the properties you're interested in displaying in your view.