like this:
var Person = context.Persons.Find(10);
Persons UpdatedPerson = new Persons ({...});
Person = UpdatedPerson;
context.SaveChanges();
But the Context is 'unchanged'?
var Person = context.Persons.Find(10);
Persons UpdatedPerson = new Persons ({...});
context.Entry(Person).CurrentValues.SetValues(UpdatedPerson);
context.SaveChanges();
UpdatedPerson must have the same key value (10) as Person. This will update all scalar and complex properties of Person but not entities related by navigation properties of Person.
Related
I have the following table structure that mixes legacy fields with an updated schema:
Coaster
Id (Int)
ParkId (Int)
Park
Id (int)
UniqueId (Guid)
So, the Coaster and Park tables are linked using the Park.Id field. The UniqueId field is not currently used in the old schema. We are migrating to a clean DB using AutoMapper, and this new schema looks like this:
Coaster
Id (Int)
ParkId (Guid)
Park
Id (Guid)
The problem I am having is doing this using AutoMapper. I've been experimenting with this code:
private ModelMapper()
{
Mapper.Initialize(x =>
{
x.AddProfile<ConvertersMappingProfile>();
});
}
// This is the part that I'm trying to work out
public ConvertersMappingProfile()
{
CreateMap<Park, NewSchema.Park>()
.ForMember(dst => dst.Id, map => map.MapFrom(src => src.ParkId));
}
In the new schema, the Park table's Id matches the old schema's UniqueId.
My question is: Because in the old schema there is no direct link to the UniqueId value of the Park table, how to do I get that value to map to the new schema using the Coaster.ParkId field to Park.Id field mapping?
I used a custom resolve to fix the problem. So I created my resolver, which pulls up a list of the items in the database (which is typically pretty small) to get all the values from the table I need, and retrieves the value. (Pre-refactored code):
public class ParkResolver : IValueResolver<Original.Park, New.Park, string> {
public string Resolve(Original.Park source, New.Park dest, string destMember, ResolutionContext context) {
List<Original.Park> list = new List<Original.Park>();
using (IDbConnection con = new SQLiteConnection(#"Data Source=C:\Users\Me\Documents\Parks.sql;")) {
con.Open();
list = con.Query<Original.Park>($"SELECT * FROM Parks WHERE Id = {source.ParkId}").ToList();
con.Close();
}
return list.FirstOrDefault().UniqueId;
}
}
And I call my custom resolver for the tables I am mapping:
CreateMap<Original.Park, New.Park>()
.ForMember(dst => dst.ParkId, map => map.MapFrom(new ParkResolver()));
Hopefully that will help someone else.
For brevity, I am going to use some simple examples to illustrate my problem. So I currently have two classes:
Class Person and Class Pet
class Person:Codable {
var name:String
var pets:[Pet]?
}
class Pet:Codable {
var name:String
weak var owner:Person?
}
How would I add the owner reference of "Pet" if I am retrieving the data from a json?
JSON would be probably like this:
[
{
"name":"John",
"pets":[
{
"name":"Meow",
"owner":"John"
},
{
"name":"Woof",
"owner":"John"
}
]
}
]
Your JSON is an array of dictionaries, each dictionary representing a person. Each person dictionary itself has an array (associated with the key pets) and each entry in that array is a dictionary representing a pet owned by the person. Your question is how you set your pet -> person weak link, you don't say what you've tried. Here is some sample pseudo-code outlining how you would process this JSON:
parsedJSON = ... // parse the JSON using favourite method, returning an array of dictionaries
allPeople = new Array // place to store all the people
for each personDictionary in parsedJSON // iterate over every person dictionary
nextPerson = new Person // create a new Person
nextPerson.name = personDictionary["name"] // set the name
nextPerson.pets = new Array // create an array for the pets
for each petDictionary in personDictionary["pets"] // iterate over the pets
nextPet = new Pet // create a new Pet
nextPet.name = petDictionary["name"] // set its name
nextPet.owner = nextPerson // set its owner <- answer to your question
nextPerson.pets.add(nextPet) // add pet to person
end for
allPeople.add(nextPerson) // add completed person to allPeople
end for
// at this point allPeople has all the people, and each person
// has all their pets, and each pet has an owner
Now just code that up in Swift 4.
I'm open to changing the json structure as well
The above pseudo-code ignores the owner field for each pet, the pets are nested inside a person dictionary representing the owner so the owner field in a pet is just repeating that information and can be dropped form the JSON.
In your internal data structures having the (weak) back link to the owner might be useful so you can keep that, as the above pseudo-code does.
If you have trouble writing the above algorithm then ask a new question showing the code you've written, describe where your issue is, and someone will undoubtedly help you. Putting a reference to this question in your new one would also be helpful so people and read the history of your question and what you've already had answered.
HTH
What is the proper way to handle unique identifiers with Node.JS and Redis? I'm looking to make the switch from MongoDB/Mongoose to Redis. There I create a Document which gets a _id field. I can use that in other Documents, to link back to them. Then I can use findByID() to retrieve the document.
I'd like to accomplish the same thing in Redis.
For simplicity, let's imagine you have two types of objects in your system: users and widgets. Each of these objects will be stored in Redis as hashes. Below are the fields that each of the object types will have in their hashes:
user
id
name
parent (which user is responsible for this user in the system)
widget
id
name
owner (which user owns this widget)
The parent field of user and the owner field of widget will act like foreign keys that reference some other object by that object's ID.
With this configuration, you need a couple of other keys in your system: user:id and widget:id. These will be used as auto increment values of the user and widget IDs. Whenever new user or widget is added to the system, you will run the INCR command:
INCR user:id # new user ID
INCR widget:id # new widget ID
You will then use the returned INCR value as the primary key for the object. Here is some pseudo-code for adding a new user:
var newUserId = redis('INCR')
var newUserKey = 'user:' + newUserId
redis('HMSET', [newUserKey,
'id', newUserId,
'name', username,
'parent', parentUserId
])
You can see how the above code could be tweaked slightly for adding a new widget.
Let's say that someone requests widget #55 from your system. First we will fetch the widget with that ID, then we will fetch the widget's owner by ID. Below is the pseudo-code for this:
var widgetId = req.params.id // 55
var widgetKey = 'widget:' + widgetId
var widgetObject = redis('HGETALL', [widgetKey])
var userKey = 'user:' + widgetObject.owner
var userObject = redis('HGETALL', [userKey])
// Do something with widgetObject and userObject
I have four Mongoose models, SoleTrader, Partnership, Company and Trust. They’re different enough that I can’t merge them all into one schema, yet similar enough that I regularly need to query or make changes to all 4 types at once and rarely care which sort they are.
Is there a way of doing this – possibly by putting all four types in a single collection – without making four database calls each time?
Since you're using mongoose-schema-extend, it seem like you could create a simple 'base' schema and extend your other schema's off that. If you want to search across all of them, use the base model.
For instance:
// base schema
var PersonSchema = new Schema({
name : String
}, {
collection : 'users', // everything will get saved in the same collection
discriminatorKey : '_type'
});
// two schema's that extend off it
var EmployeeSchema = PersonSchema.extend({ department : String });
var EmployerSchema = PersonSchema.extend({});
// materialize all three into models
var Person = mongoose.model('Person', PersonSchema);
var Employee = mongoose.model('Employee', EmployeeSchema);
var Employer = mongoose.model('Employer', EmployerSchema);
...
// create some people
new Employee({
name : 'Homer Simpson',
department : 'Safety'
}).save(...);
new Employer({
name : 'Charles Montgomery Burns',
}).save(...);
...
// search across employers and employees
Person.find({ ... }, function(err, people) {
...
});
However, I have to say that the advertised behaviour of find() returning the correct model instance according to the discriminator key doesn't work for me.
I was working with out of the box authentication, with service stack, and it works great. So, right now, I am mocking up a user with the following lines of code, taken from ServiceStack examples:
var userRep = new InMemoryAuthRepository();
container.Register<IUserAuthRepository>(userRep);
string hash;
string salt;
new SaltedHash().GetHashAndSaltString("test", out hash, out salt);
userRep.CreateUserAuth(new UserAuth
{
Id = 1,
DisplayName = "DisplayName",
Email = "as#if.com",
UserName = "john",
FirstName = "FirstName",
LastName = "LastName",
PasswordHash = hash,
Salt = salt,
}, "test");
Is there someway I can define the fields in userRep? For example, lets say I want to have the field portalid as well as part of the UserAuth object? How would I go about doing this? Can I just modify the InMemoryAuthRepository class?
You can't change the Schema of ServiceStack's built-in UserAuth DTOs, but it does provide a few extensibility points which are explained in detail in this answer where you could use the RefId and RefIdStr fields to reference your own custom tables or add metadata in the UserAuth row by adding metadata to the Dictionary<string,string> Meta collection.