How to specify a column Name for EF5 navigation property - entity-framework-5

I'm using EF5 code first to generate my database schema, but my new navigation property is being named in an undesirable way in the table. here is the model I'm working with.
public class User
{
[Key]
public long UserId { get; set; }
...
**public virtual ICollection<ImagePermission> KeepThisNavigationName { get; set; }**
}
However, After I've updated my database and examine the table columns, the column is named:
dbo.ImagePermission.User_UserId
And I would like it to be named
dbo.ImagePermission.KeepThisNavigationName_UserId
I believe there is a way to do this using the Fluent API, but after many failed attempts, I can't get the desired outcome.
P.s. The 'ImagePermission' Entity is currently still in development, so I would prefer to drop the migration which creates this table so I can create this column name correctly during the table create, rather than having additional code to update the column name.
Many thanks, Oliver

The correct mapping with Fluent API would be:
modelBuilder.Entity<User>()
.HasMany(u => u.KeepThisNavigationName)
.WithOptional() // or WithRequired()
.Map(m => m.MapKey("KeepThisNavigationName_UserId"));
If you have a navigation property in ImagePermission refering to User you need to use WithOptional(i => i.User) (or WithRequired(i => i.User)) instead of the parameterless version.

Related

How to extend the core customer table?

I created a custom table with additional settings for customers. Next I added a field to the customer core table in which I'd like to store the id choice per customer. I extended with EntityExtensionInterface the customerDefinition :
public function extendFields(FieldCollection $collection): void
{
$collection->add(
(new OneToOneAssociationField(
'customerSetting',
'customer_setting',
'id',
WdtCustomerSettingsDefinition::class,
true
))->addFlags(new Inherited())
);
}
public function getDefinitionClass(): string
{
return CustomerDefinition::class;
}
When I manually manipulate the customer table, with an id from my custom table in the added field, I can retrieve and use the settings from my custom table in the storefront.
For the backend I created a single select to the entity custom_table,
<sw-entity-single-select entity="wdt_customer_settings" v-model="customer.extensions.customerSetting.id" >
</sw-entity-single-select>
and with the manually 'injected' id from the custom table, this choice indicates indeed 'selected' However, after changing to another choice and saving results in an error: Customer could not be saved.
What am I missing?
You should look always to the ajax responses. There is the explict error which is occured. Do you added some boilerplate code to check that your extensions is always available? Otherwise it would cause issues on new entities

Custom Fields for IdentityUser

I am trying to add custom fields for my IdentityUser. I have been through the documentation and also several articles that I've found online. I was able to figure out how to add custom fields, but I'm not sure how to set constraints on them. None of the articles I've found have covered this topic.
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
public DateTime RegistrationDate { get; set; }
public string IPAddress { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
My code example is above. I have added 2 fields. RegistrationDate and IPAddress. I've used PowerShell to create the migrations and update the database.
My questions are this:
How do I set a default value for RegistrationDate? I wanted it to be SQL Now(). I can make the change in the database after the migration, but that gets my code and database out of sync.
On IPAddress, I want to have the maximum size be 39 characters. When I update the database, the field is created as NVARCHAR(MAX) NULL. I want it to be NVARCHAR(39) NOT NULL. I can't see anyway to do that in the IdentityUser.
Lastly, what if I wanted to store the IPAddress as VARBINARY or BINARY? That's not even a data type that C# will accept.
I am able to go into the migration files and make some changes after creating the migration, but those changes are not reflected in the database. If I try to re-run Update-database from PowerShell, I get an error saying that there are no changes to update.
On top of that. I don't know if I should be manually updating the migration files, since they are generated code.
public partial class IPAddress : DbMigration
{
public override void Up()
{
AddColumn("dbo.AspNetUsers", "IPAddress", c => c.String(nullable: false, maxLength: 39));
}
public override void Down()
{
DropColumn("dbo.AspNetUsers", "IPAddress");
}
}
I'm using Visual Studio 2015 and version 4.6.
Thanks
1) To have a default date on your RegistrationDate you need to create a default constructor of ApplicationUser that sets your date to be whatever you need:
public ApplicationUser()
{
RegistrationDate = DateTime.Now();
}
2) To change the size of the field you need to apply [MaxLength(39)] attribute on your IPAddress field:
[MaxLength(39)]
public string IPAddress { get; set; }
3) To get BINARY you need to use byte[] type in C#. (ref: https://stackoverflow.com/a/1158670/809357)
4) You should not change the scripts for migrations manually - migrations contain XML snapshot of the database and keeps that snapshot in the __MigrationsHistory table. So if you change the migration script, the snapshot will not be re-generated and EF won't pick up your changes.
When you change your data model you either create a new migration via add-migration NewMigrationName or rollback your DB to a previous migration state via update-database -Target PreviousMigrationName and then re-generate existing migration via add-migration ExistingMigrationName -Force and then do Update-database

how can i fill controller with data - SQL Function in Entity Framework?

i have create an sql function in my database that take to Date params and get data from 5 tables.
after that add it to project as entity framework from database and the code generated is:
[DbFunction("Dr_EmploEntities", "SelectEmployee")]
public virtual IQueryable SelectEmployee(Nullable frm_date, Nullable to_date)
{
var frm_dateParameter = frm_date.HasValue ?
new ObjectParameter("frm_date", frm_date) :
new ObjectParameter("frm_date", typeof(DateTime));
var to_dateParameter = to_date.HasValue ?
new ObjectParameter("to_date", to_date) :
new ObjectParameter("to_date", typeof(DateTime));
return ((IObjectContextAdapter)this).ObjectContext.CreateQuery("[Dr_EmploEntities].[SelectEmployee](#frm_date, #to_date)", frm_dateParameter, to_dateParameter);
}
public DbSet SelectEmployee_Result { get; set; }
as you see i have now "SelectEmployee_Result" that don't take any params, and "SelectEmployee" that take two date params.
after that i have create an controller for "SelectEmployee_Result" class.
after that i run my project Index View that working with "SelectEmployee_Result" class give me err:
"The type 'SelectEmployee_Result' is mapped as a complex type. The Set method, DbSet objects, and DbEntityEntry objects can only be used with entity types, not complex types."
and i make breakpoint and see that "SelectEmployee_Result" has no data so i change the Index Code in controller and fill "SelectEmployee" with two date params
and when run got same err msg too.
so how can i fill "SelectEmployee_Result" from the beginning with data between two dates to let me use it in all views ?
all what i need here is view data i got i edit before saving it in database Like using DataTable but i need to do that from Entity with sql function
and what is difference between "SelectEmployee" that is my function name and that is need two params and "SelectEmployee_Result"?

Fluent NHibernate - Multiple collections in the same table

Im working on rebuilding a clients software and they want to keep their database as unmodified as possible.
I got a table where they collect users and orders for different companies, no biggie there but the twist is they do it for multiple entities.
for example the table looks like this:
ID
UserID
Index
CompanyID
Type
lets say they got entities like Project and Workflow, then the Type column would be 'P' for projects and 'W' for workflows. So on a ID is the ID of a Project or Workflow Identity. UserID is always a foreign key to a User entity and Index is the order that the user is used when this Project/Workflow is used. And CompanyID is what company owns project or workflow entity.
I have tried to search google for this but i came up with nothing.
What i want is on a Template entity map two collections say StandardProjectUsers and StandardWorkflowUsers and they should collect them from correct entities with a user and index for current company.
Is this at all possible with fluent nhibernate ?
A nice article on how to do it: http://www.philliphaydon.com/2011/08/fluent-nhibernate-table-inheritance-discriminators/
You are looking at a table-per-hierarchy strategy.
In a nutshell you use:
public class BaseClassMap : ClassMap<BaseClass>
{
public BaseClassMap()
{
DiscriminateSubClassesOnColumn("Type");
...
}
}
public class WorkflowMap : SubclassMap<Workflow>
{
public WorkflowMap()
{
DiscriminatorValue("W");
...
}
}
public class ProjectMap : SubclassMap<Project>
{
public ProjectMap()
{
DiscriminatorValue("P");
...
}
}

Adding custom field to User programmatically through liferay.expando

I am trying to add fields to com.liferay.portal.model.User, an extra attribute using Expando. Can someone explain to me how this method is adding a field because docs don't have much description.
private void addUserCustomAttribute(long companyId, ExpandoTable userExpandoTable, String attributeName, int type) throws PortalException, SystemException {
ExpandoColumnLocalServiceUtil.getColumn(userExpandoTable.getTableId(), attributeName); //should be addColumn(long tableId, String name, int type) ???
} //and where can find type description couse i have very specific type, Map(String,Object) couse in ExpandoColumnConstants didn't see it
I have taken this from Liferay Expando Wiki's Adding User Custom Attributes.
When should I call this all? Where to put this in my project? What change is required or everything needs to be changed to call it.
Some good tutorial will be nice because it's hard to find something from 0 to end, always found only some part with no explanation.
The question is not very clear. But if you simply want to add a custom attribute for your User then you can refer to my answer here and reproduced for your reference:
Custom field for the user-entity can be created through:
Control Panel -> Portal -> Custom Fields -> User.
And programmatically can be created as follows:
user.getExpandoBridge().addAttribute("yourCustomFieldKey");
Then set the value as:
user.getExpandoBridge().setAttribute("yourCustomFieldKey", "valueForCustomField");
If your custom field is already present you can check like this:
if (user.getExpandoBridge().hasAttribute("yourCustomFieldKey")) { ... };
The data is stored in tables prefixed with "EXPANDO":
EXPANDOCOLUMN: stores the custom field key and other settings
(contains the tableId refrences)
EXPANDODATA: stores the custom field value for the key (contains the
columnId and tableId refrences)
EXPANDOTABLE: stores for which liferay entity (user) are you adding
the custom field
EXPANDOROW: stores linking information between a user and its values
(contains tableId and userId refrences)
Hope this helps.
If your custom field is multivalue, you can use this:
String customVal = "yourCustomFieldValue";
user.getExpandoBridge().setAttribute("yourCustomFieldKey", new String[] {customVal }, false);
The last parameter set to "false" avoids permission check.

Resources