Saving a Hashtable using Mongo & the Play framework? - mongodb

I've got a model defined like the following...
#MongoEntity
public class Ent extends MongoModel{
public Hashtable<Integer, CustomType> fil;
public int ID;
public Ent(){
fil = new Hashtable<Integer, CustomType>();
}
}
CustomType is a datatype I've created which basically holds a list of items (among other things). At some point in my web application I update the hashtable from a controller and then read back the size of the item I just updated. Like the following...
public static void addToHash(CustomType type, int ID, int key){
//First I add an element to the list I'm storing in custom type.
Ent ent = Ent.find("byID",ID).first();
CustomType element = user.fil.get(key);
if(element == null) element = new CustomType();
element.add(type);
ent.save();
//Next I reset the variables and read back the value I just stored..
ent = null;
ent = User.find("byID",ID).first();
element = ent.fil.get(ID);
System.out.println("SIZE = " + element.size()); //null pointer here
}
As you can see by my above example I add the element, save the model and then attempt to read back what I have just added and it has not been saved. The above model Ent is a minimal version of the entire Model I'm actually using. All other values in the model including List's, String's, Integer's etc. update correctly when they're updated but this Hashtable I'm storing isn't. Why would this be happening and how could I correct it?

You should probably post on the play framework forum for better help..
Alternatives for a mongodb framework are morphia and springdata which have good documentation.
Not sure how Play maps a hash table to a document value, but it seems it cannot update just the hash table using a mongo operator.
You should be able to mark the whole document for update which would work but slower.

Related

Umbraco 7 generic node class

With the help of other Stackoverflow users, I have gone some way to my solution but have come to a halt.
I would like to build some generic classes in an app_code .cshtml file eg one would be to return property values from documents from a function eg
public static string docFieldValue(int docID,string strPropertyName){
var umbracoHelper = new Umbraco.Web.UmbracoHelper(Umbraco.Web.UmbracoContext.Current);
var strValue = "";
try{
strValue = umbracoHelper.Content(docID).GetPropertyValue(strPropertyName).ToString();
}
catch(Exception ex){
strValue = "Error - invalid document field name (" + strPropertyName + ")";
}
var nContent = new HtmlString(strValue);
return nContent;
}
This works ok for returning one field (ie property) from a document. However, if I wanted to return 2 or more, ideally, I would store the returned node in a variable or class and then be able to fetch property values repeatedly without having to look up the document with each call
ie without calling
umbracoHelper.Content(docID).GetPropertyValue(strPropertyName).ToString();
with different strPropertyName parameters each time, as I assume that will mean multiple reads from the database).
I tried to build a class, with its properties to hold the returned node
using Umbraco.Web;
using Umbraco.Core.Models;
...
public static Umbraco.Web.UmbracoHelper umbracoHelper = new Umbraco.Web.UmbracoHelper(Umbraco.Web.UmbracoContext.Current);
public static IPublishedContent docNode;
...
docNode = umbracoHelper.Content(docID);
but this crashed the code. Can I store the node in a property on a class, and if so, what type is it?
First of all, using a .cshtml file is unnecessary, use a .cs file instead :-) CSHTML files are for Razor code and HTML and stuff, CS files are for "pure" C#. That might also explain why your last idea crashes.
Second of all, UmbracoHelper uses Umbracos own cache, which means that the database is NOT touched with every request. I would at least define the umbracoHelper object outside of the method (so it gets reused every time the method is called instead of reinitialised).
Also, beware that property values can contain all kinds of other object types than strings.
EDIT
This is an example of the entire class file - my example namespace is Umbraco7 and my example class name is Helpers:
using Umbraco.Web;
namespace Umbraco7
{
public class Helpers
{
private static UmbracoHelper umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
private static dynamic docNode;
public static string docFieldValue(int docID, string strPropertyName)
{
docNode = umbracoHelper.Content(docID);
return docNode.GetPropertyValue(strPropertyName).ToString();
}
}
}
This is an example how the function is called inside a View (.cshtml file inside Views folder):
#Helpers.docFieldValue(1076, "introduction")
Helpers, again, is the class name I chose. It can be "anything" you want. I've just tested this and it works.
I suggest you read up on general ASP.NET MVC and Razor development, since this is not very Umbraco specific.

Filehelpers and Entity Framework

I'm using Filehelpers to parse a very wide, fixed format file and want to be able to take the resulting object and load it into a DB using EF. I'm getting a missing key error when I try to load the object into the DB and when I try and add an Id I get a Filehelpers error. So it seems like either fix breaks the other. I know I can map a Filehelpers object to a POCO object and load that but I'm dealing with dozens (sometimes hundreds of columns) so I would rather not have to go through that hassle.
I'm also open to other suggestions for parsing a fixed width file and loading the results into a DB. One option of course is to use an ETL tool but I'd rather do this in code.
Thanks!
This is the FileHelpers class:
public class AccountBalanceDetail
{
[FieldHidden]
public int Id; // Added to try and get EF to work
[FieldFixedLength(1)]
public string RecordNuber;
[FieldFixedLength(3)]
public string Branch;
// Additional fields below
}
And this is the method that's processing the file:
public static bool ProcessFile()
{
var dir = Properties.Settings.Default.DataDirectory;
var engine = new MultiRecordEngine(typeof(AccountBalanceHeader), typeof(AccountBalanceDetail), typeof(AccountBalanceTrailer));
engine.RecordSelector = new RecordTypeSelector(CustomSelector);
var fileName = dir + "\\MOCK_ACCTBAL_L1500.txt";
var res = engine.ReadFile(fileName);
foreach (var rec in res)
{
var type = rec.GetType();
if (type.Name == "AccountBalanceHeader") continue;
if (type.Name == "AccountBalanceTrailer") continue;
var data = rec as AccountBalanceDetail; // Throws an error if AccountBalanceDetail.Id has a getter and setter
using (var ctx = new ApplicationDbContext())
{
// Throws an error if there is no valid Id on AccountBalanceDetail
// EntityType 'AccountBalanceDetail' has no key defined. Define the key for this EntityType.
ctx.AccountBalanceDetails.Add(data);
ctx.SaveChanges();
}
//Console.WriteLine(rec.ToString());
}
return true;
}
Entity Framework needs the key to be a property, not a field, so you could try declaring it instead as:
public int Id {get; set;}
I suspect FileHelpers might well be confused by the autogenerated backing field, so you might need to do it long form in order to be able to mark the backing field with the [FieldHidden] attribute, i.e.,
[FieldHidden]
private int _Id;
public int Id
{
get { return _Id; }
set { _Id = value; }
}
However, you are trying to use the same class for two unrelated purposes and this is generally bad design. On the one hand AccountBalanceDetail is the spec for the import format. On the other you are also trying to use it to describe the Entity. Instead you should create separate classes and map between the two with a LINQ function or a library like AutoMapper.

Entity Framework refuses to save value on new column

I just changed our database, adding a new column to a table and setting it as a foreign key. We're using EF4 Database first, so I updated the model from the DB, added my new field to the DTOs and everything looked great until I tried to save data to it.
The new column is called DiaryEventId, and because it's a FK there's also a virtual property on the object called DiaryEvent. Here's what the code looks like:
public void SaveDocument(Guid CaseId, string diaryText, string ActivityType)
{
Guid eventTypeId = RepositoryHelper.GetDiaryEventFromCache("Document Uploaded", _commonQueryContext);
//this wanders off and created a diary event object, adds it to
//the context and returns its ID
Guid diaryId = RepositoryHelper.AuditEvent(CaseId, diaryText, commonUpdateContext);
Entities.DocumentMetadata docData = new Entities.DocumentMetadata()
{
Id = Guid.NewGuid();,
ActivityType = activityType,
DiaryEventId = diaryId
};
_commonUpdateContext.DocumentMetadatas.Add(docData);
_commonUpdateContext.SaveChanges();
}
This compiles and runs fine, and when you step through it it appears to function as expected - diaryId is generated and set on the object. But in the DB, it always appears as null.
I've tried calling SaveChanges after adding the diary event (to make sure the key has something to connect to) and I've tried adding the actual DiaryEvent object to the virtual property rather than just the ID - both have the same effect.
When I watch what's going on in SQL Profiler, I can see that the INSERT statement simply ignores my new column completely - it's not listed in the insert columns at all.
Really got no idea what's going on. Any ideas?
Try modifying the object after adding it to the context, just as a test.
_commonUpdateContext.DocumentMetadatas.Add(docData);
Entities.DocumentMetadata docData = new Entities.DocumentMetadata()
{
Id = Guid.NewGuid();,
ActivityType = activityType,
DiaryEventId = diaryId
};
_commonUpdateContext.SaveChanges();
Or is this perhaps a typo?
Entities.DocumentMetadata docData = new Entities.DocumentMetadata()
{
Id = Guid.NewGuid();, <-------------typo?
Beyond that, it will require a bit of info on how you have your entities mapped out. Is there a navigation property between DiaryEvent and DocumentMetadata? Is the key defined as nullable (I'm assuming it is)? Is ActivityType getting persisted correctly?

Wicket - Wrapped collection Model "transformation"

I have a domain object which has a collection of primitive values, which represent the primary keys of another domain object ("Person").
I have a Wicket component that takes IModel<List<Person>>, and allows you to view, remove, and add Persons to the list.
I would like to write a wrapper which implements IModel<List<Person>>, but which is backed by a PropertyModel<List<Long>> from the original domain object.
View-only is easy (Scala syntax for brevity):
class PersonModel(wrappedModel: IModel[List[Long]]) extends LoadableDetachableModel[List[Person]] {
#SpringBean dao: PersonDao =_
def load: List[Person] = {
// Returns a collection of Persons for each id
wrappedModel.getObject().map { id: Long =>
dao.getPerson(id)
}
}
}
But how might I write this to allow for adding and removing from the original List of Longs?
Or is a Model not the best place to do this translation?
Thanks!
You can do something like this:
class PersonModel extends Model<List<Person>> {
private transient List<Person> cache;
private IModel<List<String>> idModel;
public PersonModel( IModel<List<String>> idModel ) {
this.idModel = idModel;
}
public List<Person> getObject() {
if ( cache == null ) {
cache = convertIdsToPersons( idModel.getObject() );
return cache;
}
public void setObject( List<Person> ob ) {
cache = null;
idModel.setObject( convertPersonsToIds( ob ) );
}
}
This isn't very good code but it shows the general idea. One thing you need to consider is how this whole thing will be serialised between requests, you might be better off extending LoadableDetachableModel instead.
Another thing is the cache: it's there to avoid having to convert the list every time getObject() is called within a request. You may or may not need it in practice (depends on a lot of factors, including the speed of the conversion), but if you use it, it means that if something else is modifying the underlying collection, the changes may not be picked up by this model.
I'm not quite sure I understand your question and I don't understand the syntax of Scala.
But, to remove an entity from a list, you can provide a link that simply removes it using your dao. You must be using a repeater to populate your Person list so each repeater entry will have its own Model which can be passed to the deletion link.
Take a look at this Wicket example that uses a link with a repeater to select a contact. You just need to adapt it to delete your Person instead of selecting it.
As for modifying the original list of Longs, you can use the ListView.removeLink() method to get a link component that removes an entry from the backing list.

Add index with entity framework code first (CTP5)

Is there a way to get EF CTP5 to create an index when it creates a schema?
Update: See here for how EF 6.1 handles this (as pointed out by juFo below).
You can take advantage of the new CTP5’s ExecuteSqlCommand method on Database class which allows raw SQL commands to be executed against the database.
The best place to invoke SqlCommand method for this purpose is inside a Seed method that has been overridden in a custom Initializer class. For example:
protected override void Seed(EntityMappingContext context)
{
context.Database.ExecuteSqlCommand("CREATE INDEX IX_NAME ON ...");
}
As some mentioned in the comments to Mortezas answer there is a CreateIndex/DropIndex method if you use migrations.
But if you are in "debug"/development mode and is changing the schema all the time and are recreating the database every time you can use the example mentioned in Morteza answer.
To make it a little easier, I have written a very simple extension method to make it strongly typed, as inspiration that I want to share with anyone who reads this question and maybe would like this approach aswell. Just change it to fit your needs and way of naming indexes.
You use it like this: context.Database.CreateUniqueIndex<User>(x => x.Name);
.
public static void CreateUniqueIndex<TModel>(this Database database, Expression<Func<TModel, object>> expression)
{
if (database == null)
throw new ArgumentNullException("database");
// Assumes singular table name matching the name of the Model type
var tableName = typeof(TModel).Name;
var columnName = GetLambdaExpressionName(expression.Body);
var indexName = string.Format("IX_{0}_{1}", tableName, columnName);
var createIndexSql = string.Format("CREATE UNIQUE INDEX {0} ON {1} ({2})", indexName, tableName, columnName);
database.ExecuteSqlCommand(createIndexSql);
}
public static string GetLambdaExpressionName(Expression expression)
{
MemberExpression memberExp = expression as MemberExpression;
if (memberExp == null)
{
// Check if it is an UnaryExpression and unwrap it
var unaryExp = expression as UnaryExpression;
if (unaryExp != null)
memberExp = unaryExp.Operand as MemberExpression;
}
if (memberExp == null)
throw new ArgumentException("Cannot get name from expression", "expression");
return memberExp.Member.Name;
}
Update: From version 6.1 and onwards there is an [Index] attribute available.
For more info, see http://msdn.microsoft.com/en-US/data/jj591583#Index
This feature should be available in the near-future via data annotations and the Fluent API. Microsoft have added it into their public backlog:
http://entityframework.codeplex.com/workitem/list/basic?keywords=DevDiv [Id=87553]
Until then, you'll need to use a seed method on a custom Initializer class to execute the SQL to create the unique index, and if you're using code-first migrations, create a new migration for adding the unique index, and use the CreateIndex and DropIndex methods in your Up and Down methods for the migration to create and drop the index.
Check my answer here Entity Framework Code First Fluent Api: Adding Indexes to columns this allows you to define multi column indexes by using attributes on properties.