I've ran into this problem in our project, where we have core DBContext
and some "pluggable" modules with their own DBContexts
, in which "module user" inherits "core (base) user". Hope that's understandable.
We also needed the ability to change (let's call it) User
to Customer
(and if needed also to another "inherited" Users
at the same time, so that user can use all those modules.
Because of that we tried using TPT inheritance, instead of TPH - but TPH would work somehow too.
One way is to use custom stored procedure as suggested by many people...
Another way that came to my mind is to send custom insert/update query to DB. In TPT it would be:
private static bool UserToCustomer(User u, Customer c)
{
try
{
string sqlcommand = "INSERT INTO [dbo].[Customers] ([Id], [Email]) VALUES (" + u.Id + ", '" + c.Email + "')";
var sqlconn = new SqlConnection(ConfigurationManager.ConnectionStrings["DBContext"].ConnectionString);
sqlconn.Open();
var sql = new SqlCommand(sqlcommand, sqlconn);
var rows = sql.ExecuteNonQuery();
sqlconn.Close();
return rows == 1;
}
catch (Exception)
{
return false;
}
}
In this scenario Customer
inherits User
and has only string Email
.
When using TPH the query would only change from INSERT ... VALUES ...
to UPDATE ... SET ... WHERE [Id] = ...
. Dont forget to change Discriminator
column too.
After next call dbcontext.Users.OfType<Customer>
there is our original user, "converted" to customer.
Bottomline: I also tried solution from another question here, which included detaching original entity (user) from ObjectStateManager
and making new entity (customer) state modified, then saving dbcontext.SaveChanges()
. That didn't work for me (neither TPH nor TPT). Either because using separate DBContexts per module, or because EntityFramework 6(.1) ignores this.
It can be found here.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…