I have searched Xodus and Xodus-DNQ and I am not able to find an idiomatic way to update an entity that is already inside a Xodus database, using Xodus-DNQ. Would I have to delete that entity and created it again afterwards, or is there a better way to do this?
Thank you
Bruno, you can just update the fields of the entity in a transaction. That's it.
Please, check the sample right in the README.md. In this block field posts of the blog is actually updated.
xodusStore.transactional {
// Create new post
val post = XdPost.new {
this.publishedAt = DateTime.now()
this.text = args.firstOrNull() ?: "Empty post"
}
// Add new post to blog
blog.posts.add(post)
}
Related
So if I want to add an artist to my website, and I create a model that holds that and some additional details like:
namespace SuperMusic.Models
{
public artist NewArtist { get; set; }
public IEnumerable<RecordCompanies> RecordCompanies
{
get { //some code to populate possible record companies }
}
Now I can have a view to create a new artist and my model could populate a drop down of record companies that the artist can be associated with.
But in my controller, I have to define "New Artist". I believe there are two ways to do this:
newArtistModel.NewArtist = context.artist.Create();
newArtistModel.NewArtist = new artist();
Is one of these more correct than the other? Or is there actually a difference in code and one of these is incorrect?
Thanks again for answer my noob questions!
the first option newArtistModel.NewArtist = context.artist.Create(); is the correct method for creating new instances as the Context will create Entity Framework aware proxy objects.
Proxy objects provide full support for navigation properties etc.
There's a more complete answer here
This artist is being used for the view, so it is only needed to render the form. There is no need for the EF context.
So when initializing the view:
newArtistModel.NewArtist = new artist();
Then, when you post the form and want to save the artist, you will need the context and can use: context.artist.Create();
SITUATION:
I have a Model and based on a users Role I want to allow the user to only update certain parts of the model. Lets say the Model has three fields. (My Model is obviously more complex than this)
MyObject
Field1
Field2
Field3
My View looks something like this:
Html.TextBoxFor(#Model.Field1)
Html.TextBoxFor(#Model.Field2)
#if(UserIsAdmin())
Html.TextBoxFor(#Model.Field3)
else
#Model.Field3
Bearing with me on the syntax (and the poor design of the example), you can see what I'm trying to do. Upon the user posting the form my controller would just take the MyObject and save it back to the database, we are using EF.
QUESTION:
My question is, is there a way to stop a user from forging a POST to be able to save data he/she should not be able to. My current idea would be to do a check in the controller to see if the user modified values he should not have. Or I could save fields individually, but neither is a convient solution.
Is there a better one?
Thanks!
Additional Info:
Not sure if this artical is relevant at all: http://blog.stevensanderson.com/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/
All three fields are from the same database table and I'm using EF to get and save the entity.
You want to make sure the user is only able to update permitted fields.
You decided that the way to achieve this is to prevent the user "forging" a response using e.g. firebug, or F12 developer tools, or GreaseMonkey, and have asked how to do this.
But the correct/best method is to check which fields the user is attempting to update, and only update those which he is permitted to update. Then it doesn't matter if they forge the request or not, they still won't be able to access anything they shouldn't. In other words, check access rights at the point of access.
Anti-forgery tokens are there to solve a separate problem, namely XSRF.
Use a viewmodel that accepts only the fields that should be updated and then populate the model with those values. You could use something like AutoMapper for mapping between the two.
My current idea would be to do a check in the controller to see if the user modified values he should not have. Or I could save fields individually, but neither is a convient solution.
You're on the right track with that idea. A typical Add() operation would look like this:
public class FooController : Controller
{
public ActionResult Add(FooViewModel viewModel)
{
if (ModelState.IsValid)
{
FooDataModel dataModel = FooMapper.MapToDataModel(viewModel, User);
FooRepository.Add(dataModel);
}
}
}
Like #VimalStan said, your FooViewModel is then a model that contains only the fields you want to let the user update. Also this still doesn't solve your problem, which should be done in your mapper (in this case FooMapper) and still check every field as #Ben suggested:
public static class FooMapper
{
public static FooDataModel Map(FooViewModel viewModel, IPrincipal user)
{
var dataModel = new FooDataModel();
dataModel.Field1 = viewModel.Field1;
dataModel.Field2 = viewModel.Field2;
if (IsAllowedToUpdateField3(user))
{
dataModel.Field3 = viewModel.Field3;
}
return dataModel;
}
public static bool IsAllowedToUpdateField3(IPrincipal user)
{
return false; // your logic
}
}
I have a page that is used to register people for training. The current page has three drop downs on it, one to select the person to register, one to select the course, and one to select the session that the course is offered. It is being requested that the page be modified to now have four groups of the Course and Session drop downs to allow for the user to register up to four classes for a person at a time. My problem arises on how to handle the form posting now. Before if a user tried to add a person to a course they were already registered for the Entity Framework model binding would catch the error and send the error message back to the form. I'm not sure how to implement this binding now that there are four instances to evaluate and save at the same time. I'm a newbie to MVC and EF so any help/direction would greatly be appreciated.
Edit: below is a piece of the orignial controller save function:
var AddToCourse = new Session_Registrant()
{
RegistrantID = RegistrantID,
SessionID = Session1,
RegistrantOrg = regOrg,
RegistrantTitle = title,
RegistedDate = DateTime.Now
};
//attempt to save
try
{
if (ModelState.IsValid)
{
db.AddToSession_Registrant(AddToCourse);
db.SaveChanges();
}
}
catch (DataException error)
{
if (error.InnerException != null)
{
if (error.InnerException.Message.Contains("UNIQUE KEY constraint"))
{
//adding custom error message to explain the failure
ModelState.AddModelError("", "Error! Registrant has already been added to this course session.");
}
}
else
{
ModelState.AddModelError("Error", error.Message);
}
}
I wonder if the problem is with the design of the function rather than the implementation. Should the problem be defined in terms of a one-to-many relationship between the registrant entity and the course/session entity.
I am also of the view that using exceptions as part of the design is bad practice and that this is a definition problem. Should you (your code) be asking questions like:
Is this a registered student
Does this student have a course already booked in this session
Is this student already registered on the course in a different session
In other words define your business rules, implement them and the problem should resolve itself into a SMOC (small matter of coding).
I am sorry if this response is not more directly helpful but I feel that this is the wrong starting point. Good luck anyway.
I am trying to add a new comment to a comment table but all records in the table are being deleted with the exception of the one I added.
As an example: Let say I have an existing comment in the database for customer 1. I want to add a new comment.
In my controller I have the following:
List<CustomerComment> comments = _commentsRepository.CustomerComments.ToList();
CustomerComment newComment = new CustomerComment()
{
CustId = 1,
RevisionNumber = revNumber,
Comment = comment,
Customer = _commentRespository.GetCustById(1),
CommentDate = DateTime.Now,
UserId = 24,
Users = _commentsRepository.GetUserById(24)
};
comments.Add(newComment);
_commentsRepository.SaveComment();
In my repository I have the following:
public Int32 SaveComment(CustomerComment comment)
{
try
{
_DB.SubmitChanges();
}
catch
{
throw;
}
return comment.CommentId;
}
While stepping through I see no changes to the data until after I create the new comment and step into the SaveComment method. What is strange is that it shows the comments already in the table for Delete and the new comment for insert.
Not understanding why it thinks the existing comments should be deleted.
I have also tried InsertOnSubmit but it does the samething so I took it out.
One thing I have noticed is that the existing comment after loading in the controller (comments) has the customer object as null. When I create the new comment I am assigning the customer to the new comment (Customer = _commentRespository.GetCustById(1).) Is this causing the delete and why doesn't the object get created and assigned when loaded.
Some additional information is that I am using POCOs and an XML mapping file.
Maybe you should not add the comment to an in memory storage try adding the new comment to the data context instead. I am presuming in your repository you have the add method... So something like _commentsRepository.add(newComment); shoukd work...
Regardless of that, why are you storing the whole customer in the database and for that matter user? you should be storing only their ids no? when you need read onky data to be thrown out into the view you may require additional data such as the customer and user details, use a dto object for that. Persistance in one thing, viewing data with certain data possibly populated from various tables is another thing...
I'm saving contacts (email, mobile phone, ICQ, AIM etc.) for people like this:
class Person {
static hasMany = {
contacts: Contact
}
}
class Contact {
String code
ContactType type
}
class ContactType {
String name
}
In my view, I've written some Templates for displaying each contact with a select-box for the contact-type and a textfield for the code, spiced up with some JavaScript for adding and deleting.
My question is: Is there an easy and elegant way to update the data similar to personInstance.properties = params or do I have to read out all the fields, deleting removed, updating changed and adding new ones?
I was looking into this some time ago but never got to refactor our code which handles parameters the old-fashioned way.
According to http://www.grails.org/Controllers+-+Data+Binding you can do something like this
def person = new Person(params['person'])
def contact = new Contact(params['contact'])
def conctactType = new ContactType(params['contactType'])
as long as request params are properly namespaced
person.contact.code
person.contact.type.name
You would still have to find out how to handle one to many. Maybe someone who knows can chip in.
Edit:
Came across this doc which describes how to handle one-to-many. It doesn't appear on the main grails site:
http://svn.codehaus.org/grails/tags/GRAILS_DOCS_1_1/src/guide/6.1.6%20Data%20Binding.gdoc