I have a problem with databases. I want to pass a user into another view as depicted below:
And as you can see I get an error that I cannot convert this Element into User.
My user strut looks like this:
struct User: Decodable, Identifiable {
public let id: String
public let name: String
public let age: Int16
public let company: String
public let about: String
public let isActive: Bool
public let email: String
public let address: String
public let registered: String
}
and my user database looks like that:
Does anyone know what may be a solution to this problem?
Well, you are fetching CoreData entity objects, but you are trying to cast a CoreData entity object to a struct type.
UserList is a CoreData entity object. The fetching is correct. However, UserView needs a object of User.
Solution 1: Convert your UserList to a User element.
Solution 2: Pass the User object to your UserView
struct UserView : View {
var userList : UserList // << Type of UserList
Related
This is my applicationDbContext class:
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, CustomRole,
int, CustomUserLogin, CustomUserRole, CustomUserClaim>
and this is my controller action method to retreive all the users with their user name:
public JsonResult GetUsers()
{
var ret = (from user in db.Users
orderby user.Id
select new
{
UserName = user.UserName,
}).AsEnumerable();
return Json(ret, JsonRequestBehavior.AllowGet);
}
Now, i am running into a problem.Whenever i execute, i got this problem----Multiple object sets per type are not supported. The object sets 'ApplicationUsers' and 'Users' can both contain instances of type 'App.Models.ApplicationUser'.
I have seen this so questions How to obtain a list of Users from ASP.NET Identity?. What is the simplest approach to solve this error.Should i follow the solution given in above question. i have already customized my user id property from string to int.
I guess you have added this to your ApplicationDbContext:
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
while through inheritance you already have it in IdentityDbContext:
public IDbSet<ApplicationUser> Users { get; set; }
Simply remove the ApplicationUsers and it will work
I would like to know if that's possible to cast a Dynamic to an other class (partially or totally)
For example, this code breaks :
class Test {
public function new() {}
public var id: String;
}
class Main {
public static function main() {
var x:Dynamic = JsonParser.parse("{\"id\":\"sdfkjsdflk\"}");
var t:Test = cast(x, Test);
}
}
with the following message
Class cast error
However, my "Test" class has an "id" field like the dynamic object. (That's an example, my use case is more complexe than that ^^)
So, I don't understand how to get an object from my Dynamic one.
This isn't exactly casting a dynamic to a class instance but may accomplish the same thing:
create an empty instance of the class with Type.createEmptyInstance
set all of the fields from the Dynamic object on the new class instance using Reflect
Example:
import haxe.Json;
class Test {
public function new() {}
public var id: String;
}
class Main {
public static function main() {
var x:Dynamic = Json.parse("{\"id\":\"sdfkjsdflk\"}");
var t:Test = Type.createEmptyInstance(Test);
for (field in Type.getInstanceFields(Test))
if (Reflect.hasField(x, field))
Reflect.setProperty(t, field, Reflect.getProperty(x, field));
trace(t.id);
}
}
You could use typedef
typedef Test = {
public var id: String;
}
class Main {
public static function main() {
var t:Test = JsonParser.parse("{\"id\":\"sdfkjsdflk\"}");
}
}
Json.parse returns anonymous structure(implementation platform dependent), typed as Dynamic. There isn't a single chance to cast it to anything but Dynamic, unless Json.parse returns Int, Float or String, which some parsers permit, but which isn't actually permitted by JSON specification.
That is this way because, the operation of casting doesn't check what fields some object have. Operation of casting only checks if the object is an instance of class you are casting to. Obviously, anonymous structure can't be an instance of any class(inside haxe abstractions at least).
However, the right way to perform the thing you seem to be trying to perform is the way stated by #Ben Morris, in his answer.
I have an aggregate named Campaigns every with a root entity named campaign, this root entity has a list of attempts (entity)
public class Attempts: IEntity<Attempts>
{
private int id;
public AttempNumber AttemptNumber {get;}
//other fields
}
public class Campaign: IEntity<Campaign> //root
{
private int id;
public IList<Attempt> {get;}
//other fields
}
Im using a method to add a campaign attempt
public virtual void AssignAttempts(Attempts att)
{
Validate.NotNull(att, "attemps are required for assignment");
this.attempts.add(att);
}
Problem comes when i try to edit a specific item in attempts list. I get Attempt by AttempNumber and pass it to editAttempt method but i dont know how to set the attempt without deleting whole list and recreate it again
public virtual void EditAttempts(Attempts att)
{
Validate.NotNull(att, "attemps are required for assignment");
}
Any help will be appreciated!
Thanks,
Pedro de la Cruz
First, I think there may be a slight problem with your domain model. It seems to me like 'Campaign' should be an aggregate root entity having a collection of 'Attempt' value objects (or entities). There is no 'Campaigns' aggregate unless you have a parent concept to a campaign which would contain a collection of campaigns. Also, there is no 'Attempts' entity. Instead a collection of 'Attempt' entities or values on the 'Campaign' entity. 'Attempt' may be an entity if it has identity outside of a 'Campaign', otherwise it is a value object. The code could be something like this:
class Campaign {
public string Id { get; set; }
public ICollection<Attempt> Attempts { get; private set; }
public Attempt GetAttempt(string id) {
return this.Attempts.FirstOrDefault(x => x.Number == id);
}
}
class Attempt {
public string Number { get; set; }
public string Attribute1 { get; set; }
}
If you retrieve an Attempt from the Campaign entity and then change some of the properties, you should not have to insert it back into the campaign entity, it is already there. This is how the code would look if you were using NHibernate (similar for other ORMs):
var campaign = this.Session.Get<Campaign>("some-id");
var attempt = campaign.GetAttempt("some-attempt-id");
attempt.Attribute1 = "some new value";
this.Session.Flush(); // will commit changes made to Attempt
You don't need an Edit method. Your code can modify the Attempts in-place, like so:
Attempt toModify = MyRepository.GetAttemptById(id);
toModify.Counter++;
toModify.Location = "Paris";
MyRepository.SaveChanges(); // to actually persist to the DB
Of course how you name the SaveChanges() is up to you, this is the way Entity Framework names its general Save method.
I'm trying to persist an object into a MongoDB, using the following bit of code:
public class myClass
{
public string Heading { get; set; }
public string Body { get; set; }
}
static void Main(string[] args)
{
var mongo = MongoServer.Create();
var db = mongo.GetDatabase("myDb");
var col = db.GetCollection<BsonDocument>("myCollection");
var myinstance = new myClass();
col.Insert(myinstance);
var query = Query.And(Query.EQ("_id", new ObjectId("4df06c23f0e7e51f087611f7)));
var res = col.Find(query);
foreach (var doc in res)
{
var obj = BsonSerializer.Deserialize<myClass>(doc);
}
}
However I get the following exception 'Unexpected element: _id' when trying to Deserialize the document.
So do I need to Deserialize in another way?? What is the preferred way of doing this?
TIA
Søren
You are searching for a given document using an ObjectId but when you save an instance of MyClass you aren't providing an Id property so the driver will create one for you (you can make any property the id by adding the [BsonId] attribute to it), when you retrieve that document you don't have an Id so you get the deserialization error.
You can add the BsonIgnorExtraElements attribute to the class as Chris said, but you should really add an Id property of type ObjectId to your class, you obviously need the Id (as you are using it in your query). As the _id property is reserved for the primary key, you are only ever going to retrieve a single document so you would be better off writing your query like this:
col.FindOneById(new ObjectId("4df06c23f0e7e51f087611f7"));
The fact that you are deserializing to an instance of MyClass once you retrieve the document lends itself to strongly typing the collection, so where you create an instance of the collection you can do this
var col = db.GetCollection<MyClass>("myCollection");
so that when you retrieve the document using the FindOneById method the driver will take care of the deserialization for you putting it all together (provided you add the Id property to the class) you could write
var col = db.GetCollection<MyClass>("myCollection");
MyClass myClass = col.FindOneById(new ObjectId("4df06c23f0e7e51f087611f7"));
One final thing to note, as the _id property is created for you on save by the driver, if you were to leave it off your MyClass instance, every time you saved that document you would get a new Id and hence a new document, so if you saved it n times you would have n documents, which probably isn't what you want.
A slight variation of Projapati's answer. First Mongo will deserialize the id value happily to a property named Id which is more chsarp-ish. But you don't necessarily need to do this if you are just retrieving data.
You can add [BsonIgnoreExtraElements] to your class and it should work. This will allow you to return a subset of the data, great for queries and view-models.
Try adding _id to your class.
This usually happens when your class doesn't have members for all fields in your document.
public class myClass
{
public ObjectId _id { get; set; }
public string Heading { get; set; }
public string Body { get; set; }
}
I have a domain object called User:
class User{
String username;
String firstName;
String lastName;
Zipcode zip;
}
I also have a Zip Code object:
class Zipcode {
String zip;
String city;
String state;
Float lat;
Float long;
}
The zipcode table should never be modified as it contains static reference data prepopulated
A user belongs to one zipcode. The user enters the zipcode as part of the User creation.
How should I model the domain objects relationship? I would like like to make sure that GORM does not attempt to update zipcodes. I would like to make sure that the user only enters valid zipcode numbers. (Which are found in the zipcode table) How do I configure the constraints on the User object? In the controller, I do the following:
def userInstance = new User(params) // where params are form values
How do I set the proper zipcode on the object?
You would not let GORM manage the zip property (and restrict GORM from doing so at a second stage), at all.
That's what mfloryan's approach tells, too; however, his approach doesn't separate concerns, properly (separation of concerns paradigm): In the MVC (Model-View-Controller) pattern, it's not the controllers' task to "model" the data model, but it's the task of the data access layer (which is - in case of GORM - the domain classes theirselves).
Thus, the User class would be implemented like that:
class User {
String userName
String firstName
String lastName
String zip
ZipCode retrieveZipCode() {
ZipCode.findByZip(zip)
}
static constraints = {
zip nullable: false, blank: false, matches: /^\d{5}/,
/* not tested at my machine: */
validator: {
if(!retrieveZipCode(it)) {
return false
}
}
}
}
Note the retrieveZipCode() method. It's not called getZipCode() as, otherwise, Hibernate would throw an exception about a "missing setter method". You can also experiment with adding a zipCode property, a getZipCode() method (that does nothing or, alternatively, throws an exception), and adding the zipCode property to the transinients definition. - Everything of this (in any combination) will not work.
Also note the constraints definition: It matches when the zip consists of exactly five digits. (I believe that's the format of ZIP codes there in the USA.)
It should also make sure that the database contains an entry for the user's ZIP code (syntax not tested).
I've changed the ZipCode class slightly (partly, to avoid a compilation error):
class ZipCode {
String zip;
String city;
String state;
Float latitude;
Float longitude;
}
And finally, there's an integration test:
class UserTests extends GroovyTestCase {
def testUserCreation() {
User user = new User(
userName: "foo", firstName: "bar",
lastName: "baz", zip: "12345")
assert user.validate()
assert user.retrieveZipCode()
user.save()
}
}
Thanks
This sounds like more of an UI issue. Do a Zipcode object lookup in the controller and set the the object located on the user. Otherwise, I can't see how a Zipcode could have been altered upon creation of a user.
save = {
params.zip.id = Zipcode.findByZip(params.zip)
def userInstance = new User(params)
}
or
save = {
def userInstance = new User(params)
userInstance.zip = Zipcode.findByZip(params.zip)
}
You should include some validation logic (if the zip is incorrect) and also consider renaming params.zip to params.userProvidedZip or something like that.
use Domain event callback
transient beforeUpdate = {
// check to make sure that the zip code value remains the same
// and is never changed...
}