ASP.NET tables and identity tables containing duplicate data - asp.net

I am using .NET Framework 4.6.1 and Entity Framework 6.0.0.0.
I am working on an ASP.NET web application (Web API). When I see my database created by Entity Framework, the tables shown below like ASP.NET User & Application Users which have some duplicate data. Also, in IdentityUserRoles and ASPNETUserRoles also having duplicate data.
I don't want to keep these duplicate tables mainly want to continue with ASP.NET tables not identity tables. How can I achieve this, and what do I need to do? Why did these duplicate tables with the same data get created?
Below is User Model I am using :-
public class User
{
[Key]
public int id { get; set; }
public string application_user_id { get; set; }
[ForeignKey("application_user_id")]
public virtual ApplicationUser applicationuser { get; set; }
public DateTime? start_date { get; set; }
public DateTime? end_date { get; set; }
public virtual ICollection<Test> Tests{ get; set; }
}

I think the answer to your question is to inherete the properties of the identity table in your tables.
To make it clear you just need to change your model into something like this:
public class user : IdentityUser
{
...
}
this way the columns in identity user will be added to the user table, in addition to your personnalized columns of the user table, I'm not sure if I made my answer clear enough but I will put here a link if you want to learn more about how to personnalize the identity tables : Custom Identity model

Related

Xamarin Forms Add List to SQL database

I have a problem. I created the following class:
public class KnownDevice
{
public int Id { get; set; }
public string Name { get; set; }
public string IP { get; set; }
public string MAC { get; set; }
public string Type { get; set; }
public List<TriangleRegistryObject> triangles { get; set; }
public List<HexagonRegistryObject> hexagons { get; set; }
}
Now, I want to create a Database on the mobile phone itself, so I use the following code to create the table:
database = DependencyService.Get<ISQLite>().GetConnection();
database.CreateTable<KnownDevice>();
But the code crashes on the second line with the error:
System.NotSupportedException: 'Don't know about
System.Collections.Generic.List`1
Now on the internet I found that it is not allowed to add a List to a database, but I need the data in that list, so I have no idea how I can fix this problem. The list can contain arround 25 rows!
Any idea how I can solve this problem?
List<TriangleRegistryObject> is not a valid type for a SQLite database value. Your type of List<TriangleRegistryObject> does not match any of the clrType == typeof(XXXX) statements, so you get that exception. You will need to rethink the class structure a little to be able to use SQLite-net like that.
For more details about the SQLite database, you could download the source file from the link for reference.
https://learn.microsoft.com/zh-cn/samples/xamarin/xamarin-forms-samples/todo/
If you want to use ou could use List, you could use SQLite-Net Extensions instead of SQLite.
You could refer to the link. The SQLite-Net Extensions library direct to specific relationships in database.
How can you store lists of objects in SQLite.net?

How to access users when Identity project uses EF Core and Class Library uses EF6 with same database

We have a .NET Core project that uses Identity 3 and IdentityDbContext using EF Core for user management. The generated tables are stored in a common SQL server database that is also being used by another project in our solution that is a .NET 4.5.2 Framework DataLayer using EF6.
(Just some more background - the .NET Core project is an authorization server that uses OpenIddict to implement OpenIdConnect and Oauth2 and is configured with Identity so that we can save users to the database and login and authenticate)
Once we've authenticated, we make calls to our API end point. The API talks to a DataLayer that works with EF6. From this project I need to fetch the logged in user and work with users for various queries. Ideally, I wanted to use and extend the same AspNetUsers table.
I am wondering what the recommended approach is here? If I try to generate a User DbContext in the EF6 project I have to add a new migration and the scaffolding wants to create a new table - one that already exists in the database. I am a little unsure about having 2 separate contexts in 2 different projects and how these can "play nice" together.
I have handled similar scenario recently. I followed this approach.
I have a separate Class Library for Data Layer, which has Identity related Repositories/Stores, migrations and DbContext. The DbContext takes connection string from the host project.
.Net Core project has connection string specified in appSettings.json. This connection string points to same database. This project implements IdentityServer3 and acts as Token Service.
.Net 4.5.2 project has connection string specified in web.config . This also points to same database. This app gets token from .net core project and uses that Bearer Token to access other APIs.
I created another project to keep the Entities and this project is referenced in both .net core and .net hosts.
This way i have one common data layer for 2 host projects and 2 different service/business layers for 2 host projects. It is working nicely for me.
As EF 7.0 doesn't support seeding, I have a console app for seeding data into database. Even this console app accesses the same database through Data Layer.
So 3 different projects are accessing same database.
I can't share my code with public. I hope this helps.
I was able to get this to work. The main issue is that I just wanted to access my AspNetUsers table that was generated by Identity 3 in the DotNet Core project in my DotNet 4.51 DataLayer class library project.
I achieved this by creating a User.cs Entity class in the class library EF 6 project and making sure it's properties matched the columns from the Identity 3 generated ApplicationUser.cs class.
User.cs
public class User{
[Key]
public string Id { get; set; }
public int AccessFailedCount { get; set; }
public string ConcurrencyStamp { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public bool LockoutEnabled { get; set; }
public DateTimeOffset? LockoutEnd { get; set; }
public string NormalizedEmail { get; set; }
public string NormalizedUserName { get; set; }
public virtual string PasswordHash { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public virtual string SecurityStamp { get; set; }
public bool TwoFactorEnabled { get; set; }
public string UserName { get; set; }
}
I then set up an EntityConfiguration to map to the AspNetUsers table
UserConfiguration.cs
public class UserConfiguration : EntityTypeConfiguration<User>
{
public UserConfiguration()
{
ToTable("AspNetUsers");
}
}
In my DbContext class I added a DbSet for my Users entity:
public virtual IDbSet<User> Users { get; set; }
I then ran the Add-Migration command to scaffold the changes. Once generated, I commented out the code and applied the migration to the database. This generates a row in the __MigrationsHistory table for the AspNetUsers table but doesn't try to recreate the table.
I was then able to successfully talk to the AspNetUsers table from the DataLayer EF6 project :)
Also it seems that I can also extend the AspNetUsers table with custom columns now by adding properties to my User.cs class and doing the migrations in the EF6 Datalayer project.

Insert record with relationship using OData

This is what my models looks like
public User
{
public string Id { get; set; }
public string Username { get; set; }
public virtual Group Group { get; set; }
}
public Group
{
public string Id { get; set; }
public string Name{ get; set; }
public virtual ICollection<User> Users { get; set; }
}
I using Azure Mobile TableController which using OData for CRUD.
Now I trying to insert new user by specifying the id of the group but instead it gives me an error which shows that instead of trying to associate it with my user model it trying to create new one:
{
"message": "The operation failed due to a conflict: 'Violation of PRIMARY KEY constraint 'PK_dbo.Groups'. Cannot insert duplicate key in object 'dbo.Groups'. The duplicate key value is (ad934511a82c4b42ae5427b5228737c6).\r\nThe statement has been terminated.'."
}
This is what my post looks like:
POST http://localhost/tables/user?ZUMO-API-VERSION=2.0.0 HTTP/1.1
{
email: 'test#test.com',
password: '#test',
group: {
id: 'ad934511a82c4b42ae5427b5228737c6'
}
}
Relationships are not directly supported in Azure Mobile Apps, but you can apply some workarounds to get it to work. Here's a blog post that walks through the scenario: 30 Days of Zumo.v2 (Azure Mobile Apps): Day 26: Relationship Advice.
The specific problem you're running into is the Entity Framework "detatched entities" problem. See e.g. Many to Many Relationships not saving. The problem is that Entity Framework has not loaded the child item into its context, so it thinks that it needs to insert the child item as well as the parent. (There have been long-standing feature requests in Entity Framework to solve this, but the feature has never been added.)
I just posted a similar answer here: How do I insert entities with a 1:n relationship in Azure App Service

Create DB context in different project

There is option to create DB which the DB context not allocated in the same MVC project,
i.e create one MVC in project A and the DB context in In project B which can use the model of model A
The reason is that I want to access to the DB from different project without any dependence
Edit.
I've created this in project A and generate the view and controller by scaffold and its working,now what should I do in project B to access to this DB context?
namespace DiffDBContext2.Models
{
public class Ad
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class AdModelDbContext : DbContext
{
public DbSet<ad> Ad { get; set; }
}
}
I am not sure what do you exactly want. But what I feel is that you want to have data access later as a separate project than your client (mvc). In this case you can have you dbcontext in another project but you need to have connection string in both mvc and data access project. when executing it always request connection string from client.

Entity Framework 4.1 Code First: Advice on persisting data from external source?

Part of my project is to persist data from another source. In this case we have an SAP data source that we will need to pull data from. I need to take the data from SAP and map it to entities I have in my application. Here is an example of an entity I have in my application:
public class Project : BaseEntity
{
public string Name { get; set; }
public string ProjectNumber { get; set; }
public string Description { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public string Currency { get; set; }
#region Navigation Properties
public virtual Address Address { get; set; }
public virtual CompanyCode CompanyCode { get; set; }
public virtual ICollection<Contact> TeamMembers { get; set; }
#endregion
}
As you can see, I have child objects that I map from SAP as well. I need some advice on the best way to insert and update my entities. I am struggling with knowing when to add (insert) entities to my context and when to attach (update) them, because SAP doesn't have knowledge of what my application may or may not have. I need to guard against duplicates, too. For example, should I perform a lookup of each child entity in my parent entity to see if they exist before I apply them to the parent? Then, add / attach the entire parent object to the context or handle each entity separately while still maintaing their relationships?
Yes you must manually test everything to make correct decision what must be inserted, updated or deleted. Depending on the application you can use some more complex queries to reduce number of round trips to the database - for example you can use single query with Contains to load all TeamMembers needed for processed Project or you can load Project with including all related data if you also need to test if project exists.
I did large synchronization application before and I end up with pre-loading all entities at the beginning with few queries and working completely in memory.
Don't forget to use DbSet's Local property or Find method to take advantage of already loaded entities.
You can also use some custom stored procedures to improve performance of this operation.

Resources