RavenDB: Updating all null values of properties of all documents to a value - ravendb

I have Documents like this in RavenDB 2.5:
public class SomeDocument {
public int Id { get;set; }
...other properties...
public bool ShowMember { get;set; }
}
with the ShowMember property being newly added.
Now I want to set ShowMember to true on all documents where it isn't set already.
I tried doing this with Eval Patching like this:
store.DatabaseCommands.UpdateByIndex("Raven/DocumentsByEntityName",
new IndexQuery { Query = "Tag:SomeDocuments" },
new ScriptedPatchRequest() {
Script = #"if(this.ShowMember == null){
this.ShowMember = true;
}" });
the operation completes without any errors, but documents that already have ShowMember set are still updated, despite the if

After playing around with it some more, doing
if(this.ShowMember == undefined)
seems to work.
Both
if(this.ShowMember == null)
and
if(!this.ShowMember)
don't work.

Related

RavenDB querying metadata

I want to prevent documents from being deleted in my project and I decided to use metadata to mark document as Archived. I used below code to do that:
public class DeleteDocumentListener : IDocumentDeleteListener
{
public void BeforeDelete(string key, object entityInstance, RavenJObject metadata)
{
metadata.Add("Archived", true);
throw new NotSupportedException();
}
}
After that I wanted to alter query to return only documents which have Archived metadata value set to false:
using (var session = _store.OpenSession())
{
var query = session.Advanced.DocumentQuery<Cutter>()
.WhereEquals("#metadata.Archived", false);
}
Unfortunately this query return empty result set. It occurs that if Document doesn't have this metadata property then above condition is treated as false. It wasn't what I expected.
How can I compose query to return Documents which don't have metadata property or this property has some value ?
You can solve it by creating an index for you Cutter documents and then query against that:
public class ArchivedIndex : AbstractIndexCreationTask<Cutter>
{
public class QueryModel
{
public bool Archived { get; set; }
}
public ArchivedIndex()
{
Map = documents => from doc in documents
select new QueryModel
{
Archived = MetadataFor(doc)["Archived"] != null && MetadataFor(doc).Value<bool>("Archived")
};
}
}
Then query it like this:
using (var session = documentStore.OpenSession())
{
var cutters = session.Query<ArchivedIndex.QueryModel, ArchivedIndex>()
.Where(x => x.Archived == false)
.OfType<Cutter>()
.ToList();
}
Hope this helps!
Quick side note. To create the index, the following code may need to be run:
new ArchivedIndex().Execute(session.Advanced.DocumentStore);

Adding Custom data Annotation using value from radio button

I am working on a sample project as my learning process. So in my project I am having an IsActive field which is a radio button . It will give either true or false. So if Is Active is False I have to make some fields mandatory like Reason,Remarks etc.I tried so many things but nothing is working for me.I am not understanding what all things I have to modify and also the places where I should modify
. I am working on MVC and consider my knowledge is low. And I have to do it as model validation so custom data annotation is what I want. Any help will be appreciated.
I created a cs file like
public class IsActiveTrue : ValidationAttribute
{
public override bool IsValid(object value)
{
var item = (Pen)value;
if (item.IsActive == false)
{
if (item.ReportNo == null || item.Reason == null || item.Remarks == null)
{
return false;
}
else
{
return true;
}
}
else
{
return true;
}
}
}
and in model
[IsActiveTrue(ErrorMessageResourceType = typeof(Resources.Resource), ErrorMessageResourceName = "Requried")]
public string Remarks { get; set; }
I am having message in the resourcse but the code is not working. please let me know wheather i am even near to the solution.

PublicAccess permissions not working in Umbraco 6

I am trying to display a table listing some documents (nodes) to the users. Those documents are protected using role permissions (right click > Public Access > Role Permissions) and I want to show only those to which this user has access.
After checking here and there, I've seen that there isn't any "Node.Permissions" way, so you have to go through Access.HasAccess().
I have used that, and I have set the permissions, but when I use the method it returns always true. What am I doing wrong?
This is the code to build the list of nodes, which works perfectly:
public static List<Node> GetAllNodeChildrenRecursively(int nodeId, string typeName)
{
var node = new Node(nodeId);
var lstNodes = new List<Node>();
foreach (Node childNode in node.Children)
{
var child = childNode;
if (child.NodeTypeAlias == typeName)
{
lstNodes.Add(childNode);
}
if (child.Children.Count > 0)
{
lstNodes.AddRange(GetAllNodeChildrenRecursively(childNode.Id, typeName));
}
}
return lstNodes;
}
This is the code to remove those I haven't access to:
var availableNodes = new List<Node>();
foreach(Node n in nodes)
{
if(Access.HasAccces(n.Id, memberId))
{
availableNodes.Add(n);
}
}
return availableNodes;
Well, Access.HasAccess returns always true, and the member I am using to test is not part of the MemberGroup that has access to that node. Am I setting permissions wrong or not checking it properly or what?
I'm lost.
As far as I know you should use the following method:
*There are a few different calls to HasAccess so it might depend on your version of Umbraco as well.
var availableNodes = new List<Node>();
try
{
//this will throw an argument exception if there is not a current user logged in
var currentMember = System.Web.Security.Membership.GetUser();
foreach (Node n in retVal)
{
if (Access.HasAccess(n.Id, n.Path, currentMember))
{
availableNodes.Add(n);
}
}
}
catch(ArgumentException e)
{
//do something when there is not a logged in member
}
return availableNodes;

CoolStorage can't set One-To-One relationship

The issue is that I can't understand how to make a OneToOne relation between two objects the way for the first object to have a link to the second and for the second to have a link to the first. Here's the code:
[MapTo("Model")]
public class Model : CSObject<Model, int>
{
[OneToOne(LocalKey = "ModelID", ForeignKey = "ModelID")]
public Product Product { get { return (Product)GetField ("Product"); } set { SetField ("Product", value); } }
}
[MapTo("Product")]
public class Product : CSObject<Product, int>
{
[OneToOne(LocalKey = "ProductID", ForeignKey = "ProductID")]
public Model Model { get { return (Model)GetField ("Model"); } set { SetField ("Model", value); } }
}
The thing is that when I create a product and a model and set the model's property "Product" to the created one and save it, the product's "Model" property doesn't get set and remains NULL. I've already tried making all the local and foreign keys for both Product's and Model's properties the same (e.g. "ModelID") but it didn't solve the problem. What is the right way of doing this?
I guess making one of them [OneToMany] will do the trick but will return a collection while I need a single object to be returned by a property.
Update
Here comes a simple solution one would call a crutch:
[OneToMany]
public CSList<Product> _ProductList { get { return (CSList<Product>)GetField ("_ProductList"); } set { SetField ("_ProductList", value); } }
[NotMapped]
public Product Product {
get {
CSList<Product> list = this._ProductList;
if (list.Count > 0)
return list [0];
return null;
}
set {
if (value != null) {
CSList<Product> list = this._ProductList;
list.RemoveAll ();
list.Add (value);
}
}
}
You can make both relations [ManyToOne]. That will work in your scenario.

Orchard Cms Fetching UserPart Field Data in LazyField<T>

I've been Following this post To get my head around Lazy field of T, Which I think I understand, But I'm having trouble getting associated Field Data for a Part loaded this way
Aim - To show photo of blog post author on a blog post.
I want to add a content part "Content Author"
The part Editor should appear as a drop down list of orchard users.
(regardless of the content owner cms users should be able to pick the author)
I have added an image upload field to the User Content Type
I want to show the image of the user on the front end in the view for the Content Author Part
For the first part I have created the content type and used the lazy Filed of UserPart to get the username. However when I try and get the associated fields for the UserPart. There dosent seem to be any.
public class ContentAuthorRecord : ContentPartRecord
{
public virtual string AuthorEmail { get; set; }
}
public class ContentAuthorPart : ContentPart<ContentAuthorRecord>
{
internal readonly LazyField<UserPart> Owner = new LazyField<UserPart>();
public string AuthorEmail
{
get { return Record.AuthorEmail; }
set { Record.AuthorEmail = value; }
}
public UserPart Author
{
get { return Owner.Value; }
set { Owner.Value = value; }
}
public string AuthorName
{
get
{
if (Author == null)
return "Riders for health";
else
{
return Author.UserName;
}
}
}
}
public class ContentAuthorHandler :ContentHandler
{
private readonly IContentManager _contentManager;
public ContentAuthorHandler(IRepository<ContentAuthorRecord> repository, IContentManager contentManager)
{
_contentManager = contentManager;
OnActivated<ContentAuthorPart>(SetUpCustomPart);
Filters.Add(StorageFilter.For(repository));
}
private void SetUpCustomPart(ActivatedContentContext content, ContentAuthorPart part)
{
// Setup the getter of the lazy field
part.Owner.Loader(() => _contentManager.Query<UserPart, UserPartRecord>().List().FirstOrDefault(x => x.Email == part.AuthorEmail));
}
}
I would expect to be able to access the field with something like
(ImageUploadField.Fields.ImageUploadField)Author.Fields.FirstOrDefault(x
=> x.Name == "Photo");
form the within the part class
( although this makes every thing a bit brittle, hard coding a field name, but I'm not sure how eles to go about it)
Further Info
I have a HeaderPart with a Image field added via the cms (not in code) in the display handler I fetch the field like this
protected override DriverResult Display(HeaderPart part, string displayType, dynamic shapeHelper)
{
if (part.HeaderType == HeaderType.Full_width_hero_image)
{
var field = (ImageUploadField) part.Fields.FirstOrDefault(f => f.Name == "HeaderImage");
if (field != null)
{
return ContentShape("Parts_Header_ImageHero",
() => shapeHelper.Parts_Header_ImageHero(ImagePath: field.ImagePath, ImageTitle: field.FileName));
}
return null;
}
if (part.HeaderType == HeaderType.Full_width_hero_video)
{
return ContentShape("Parts_Header_VideoHero", () => shapeHelper.Parts_Header_VideoHero(VideoUrl: part.VideoUrl));
}
if (part.HeaderType == HeaderType.Body_width_video)
{
return ContentShape("Parts_Header_VideoBody", () => shapeHelper.Parts_Header_VideoBody(VideoUrl: part.VideoUrl));
}
return null;
}
This works, But I can do the same for a part loaded into a lazy field.
Cast to dynamic first, then the syntax becomes much simpler: ((dynamic)part.ContentItem).NameOfTheType.NameOfTheField.NameOfTheProperty
If you have added the fields to the User content type via the CMS interface, it may have added the fields to a different part to the one you expect. If you are adding fields to the User content type, by default it will have added the fields to a new part called 'User', not 'UserPart'. Try to following to search all parts in the content item:
(ImageUploadField.Fields.ImageUploadField)Author.ContentItem.Parts
.SelectMany(p => p.Fields).FirstOrDefault(f => f.Name == "Photo");
or directly from the 'User' part:
(ImageUploadField.Fields.ImageUploadField)Author.ContentItem.Parts
.First(p => p.PartDefinition.Name == p.ContentItem.ContentType).Fields
.FirstOrDefault(f => f.Name == "Photo");