|
|
Comments and Discussions
|
|
 |

|
I don't think server mode would be an issue if it is done right. I mean you were almost there with your original implementation. Basically it is just removing the types you need to specify witch gives you the nice query syntax and then also casting the response.
The main thing i see having an issue with this method of query is casting the result if you query the entity directly. I have a version of count that looks like it will work on entity and view row schema but i am not sure i can do that for query as the current results for searching on the entity itself does not return the entity but the main view which would break my casting. That said that is an acceptable loss in my case for nice simple syntax. If done at a lower level in your DB lib my base classes and interfaces probably would not be needed either.
Can't wait to see what you manage to do with this. If you need me to test anything let me know
|
|
|
|

|
The following is working in embedded mode (views are the same, nothing changed):
var q = rap.Query<SalesInvoiceView.RowSchema>(x => x.Serial < 100, 0, 10); string s = q.Rows[0].CustomerName;
The constraint is that you have to supply the schema type for the view you want.
I'm working on the server mode conversion...
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Nice!
Thanks for making the change! Willit work for other methods like Count as well?
|
|
|
|

|
There is no reason why not (if I can get the server part working).
Actually if I can force people to obey this constraint (that you have to specify the views schema when querying [currently you can use anything and it will find the view]) then I can remove a lot of code, which is really nice.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
The server side is working
The only problem is the ServerSide() method calls which seems to be loading the same type from different paths hence I'm getting an invalid cast exception in tcp client server mode (seems to be a problem with LoadFrom())
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Sounds like you are getting closer. I have only used the embedded mode so far so have not hit the issues you are talking about. That said if it is loading the same classes up in different namespace/path that is a little worrying
|
|
|
|

|
only partly related but does attribute [RegisterView] mean i don't need to manually register my views via a method call?
|
|
|
|

|
The attribute is only used in server mode for automatic registration.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Any reason for that or a reason why the embedded constructor could not take a boolean to tell it to use the attribute or not. Just seems like it could make it a lot less hassle in 90% of cases and still give people flexibility if they want it.
|
|
|
|

|
That would imply and require the user have an "Extensions" folder. The embedded mode is really intended for simple apps, where you would probably have all your code in a single project.
I am open to votes on this.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Really? Can't you check all the classes already in the app domain for that attribute as well?
|
|
|
|

|
Actually it is loading the exact same dll (views.dll) from 2 different places one from the extensions folder and the other from the bin folder (in server mode).
It's a "feature" of LoadFrom(), it could be fixed if I give it a strong name I will test this.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Fixed!!
I had an extra view.dll deployed beside the testing.exe which I deleted and everything works.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
sweet. Will you be updating the code on codeplex soon? I would love to test it.
|
|
|
|

|
Using latest source on codeplex and the changes look good so far. Have not hit an issue yet
|
|
|
|

|
Great data base lib only thing missing is that it is not on nuget yet. Hopefully the author adds it soon.
Article is great and so is the software. Almost impossible to find that.
|
|
|
|

|
Hi,
I've an app that pulls a number of objects from RaporDB then allows the user to edit 1 of the properties of these objects and then writes the changes back to RaptorDB again. I'm getting some strange behavior where occasionally objects will get duplicated when I save them...instead of overwriting the original object. The app is a WPF app, using a DataGrid for the editing.
I'm displaying the list of views returned for a query against RaptorDB in the DataGrid. Then when the user edits one of these objects I'm fetching the original object, updating it with the changed value. Lastly I save this object back to the DB. Most of the time this is working but about 30% of the time (as a rough estimate) I'm ending up with a duplicate object with the same docid but with the old value of the updated property. Any idea on what I'm doing wrong here?
A simplified version of the code is here:
My objects that are stored in RaptorDB
public class Sample
{
public Guid ID;
public string Name;
public string FieldTwo;
public ScanContainer()
{
ID = Guid.NewGuid();
Name = "Sample Name";
FieldTwo = DateTime.Now.ToString("o");
}
}
public class SampleView : View<Sample>
{
public class RowSchema : RDBSchema
{
public string Name;
public string FieldTwo;
}
public SampleView()
{
this.Name = "Sample";
this.Description = "A primary view for Samples";
this.isPrimaryList = true;
this.isActive = true;
this.BackgroundIndexing = true;
this.Schema = typeof(SampleView.RowSchema);
this.AddFireOnTypes(typeof(Sample));
this.Mapper = (api, docid, doc) =>
{
api.EmitObject(docid, doc);
};
}
}
Some DB code
public static class DBHelper
{
public static RaptorDB.RaptorDB DB = RaptorDB.RaptorDB.Open("_data");
public static void Close()
{
DB.Shutdown();
}
public static object FetchDocument(object ViewRowSchema)
{
Guid objectId = ((RDBSchema)ViewRowSchema).docid;
if(objectId != Guid.Empty && objectId != null)
{
return DB.Fetch(objectId);
}
else
return null;
}
public static List<object> GetList()
{
DB.RegisterView(new SampleView());
List<object> result = DB.Query(typeof(Sample)).Rows;
return result;
}
public static bool SaveSampleListNameChange(object SampleViewRowSchema, string newValue)
{
DB.RegisterView(new SampleView());
Sample toUpdate =(Sample) FetchDocument(SampleViewRowSchema);
if(toUpdate != null)
{
toUpdate.Name = newValue;
return DB.Save(toUpdate.ID, toUpdate);
}
else
return false;
}
}
The XAML code for my data grid
<DataGrid Name="sampleList_DataGrid"
ItemsSource="{Binding}"
CanUserAddRows="False"
AutoGenerateColumns="False"
CellEditEnding="DataGrid_CellEditEnding">
<DataGrid.Columns>
<DataGridTextColumn
Binding="{Binding Name}"
Width="*"
Header="Name"/>
<DataGridTextColumn
Header="Field Two"
Binding="{Binding FieldTwo}"
Width="*"
IsReadOnly="True"/>
</DataGrid.Columns>
</DataGrid>
The C# code behind the datagrid.
void PopulateDatagrid()
{
sampleList_DataGrid.ItemsSource = DBHelper.GetSampleList();
}
void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if(e.EditAction == DataGridEditAction.Commit)
{
TextBox textBox = e.EditingElement as TextBox;
if(!string.IsNullOrWhiteSpace(textBox.Text))
{
if(!DBHelper.SaveSampleListNameChange(e.Row.Item, textBox.Text))
MessageBox.Show("Unable to save edit");
}
}
}
|
|
|
|

|
Try setting this.BackgroundIndexing = false; in the view.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Just tried that, still seeing the same issues.
Any other ideas, I presume it shouldn't be possible to have two objects in the database with the same docid?
Thank you for the quick reply!
|
|
|
|

|
Try this.DeleteBeforeInsert=true; also in your view.
It is possible to have objects with the same docid in the storage file which would mean version-ed objects, but in the view you should not see duplicates with the above parameter set unless you have a "details view" where each row is a detail row of the main document.
Also try deleting the view folder and restarting, so the view is rebuilt and see if you have duplicates then also.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Ok, with this.DeleteBeforeInsert=true; I'm still seeing the issue.
But I tried deleting the view folder and that has removed the duplicate objects. Also it doesn't appear to be re-occurring. So was there some issue with my view? Anything else I can do to find out what happened and try to avoid it happening again.
Thanks for the help, this has been messing with my head for a few hours.
|
|
|
|

|
It's hard to say what the problem was, it could have been an inconsistent deleted index in the view, or a concurrency condition. Most probably the first since a view rebuild fixed it.
Let me know if it happens again.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
I will, thanks for the help
|
|
|
|

|
Hi Mehdi,
How can I discard deleted objects ?
ES ( where userId is a string ):
Models.User usr = (Models.User)raptorDB.Fetch(new Guid(userId));
raptorDB.delete(usr.ID);
var qry = raptorDB.Query(typeof(Models.User));
Most probably I did not understand how deletion work.
Thanks in advance
|
|
|
|

|
Thanks Antonello!
This could be a bug. I will look into it.
Delete works by flagging the item and does not actually delete anything.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Hi Mehdi.
Thaks for your replay ,
Yes... I read your documentation about logical deletion but I was in doubt if this delete status were considered by RaptorDB during queries.
Sincerely
Antonello
|
|
|
|

|
Hi Mehdi.
Don't waste your time Most probably my problem is caused from a schema changing in view... As soon as I'll get time I'll try to reproduce the problem and the flow in a precise and clear way.
|
|
|
|

|
I was wondering if Dynamic objects are supported at all. I currently use them a lot as a way to let plugins add more data to my main objects or add new objects without having to change my core code/libraries. Basically at start-up i load a config that applies strict rules on my Dynamic objects and the properties and data types of each field as well as specifies if they are used for searching etc.
I am guessing i would need to change that design to make it work with your database and maybe look at some auto generated classes that then get compiled or something so that i have the data class and the required views for your database. Is there anyway it could all be done from code instead?
|
|
|
|

|
Currently the serializers in RaptorDB namely fastJSON and fastBinaryJSON do not handle dynamic objects.
Personally I have a problem with dynamic objects since I always know what object I am dealing with in my code and any code in between is just a pass through and maybe using base class inheritance, so there is no usecase for it.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
In my case my objects are a class that extends DynamicObject. They have a few normal properties on the class but the rest are Dynamic properties which is just an easier way to access the dictionary of name value pairs the class contains. I am open to ideas but basically my system just stores data and links plugins together and the idea is each plugin can use the data from the other plugins or add to the data from the other plugins. That is where my issue is as the idea is the plugins will be written by others online and can easily add to the data while still been accessible to other plugins. Some sort of generic document model with type safety was about the only structure i could think of that would work short of passing something like a json string around. Is there something that would work well with your database that may work in that sore of use case?
|
|
|
|

|
Hi,
First thanks for this great project. I've only started looking at it recently but I like what I see so far.
I was having issues retrieving a particular type of object from the db with the following stack trace
System.NullReferenceException: Object reference not set to an instance of an object.
at fastBinaryJSON.BJSON.CreateGenericList(List`1 data, Type pt, Type bt, Dictionary`2 globalTypes) in v1.8.3\RaptorDB.Common\fastBinaryJSON\BJSON.cs:line 508
at fastBinaryJSON.BJSON.ParseDictionary(Dictionary`2 d, Dictionary`2 globaltypes, Type type, Object input) in v1.8.3\RaptorDB.Common\fastBinaryJSON\BJSON.cs:line 426
at fastBinaryJSON.BJSON.ParseDictionary(Dictionary`2 d, Dictionary`2 globaltypes, Type type, Object input) in v1.8.3\RaptorDB.Common\fastBinaryJSON\BJSON.cs:line 453
at fastBinaryJSON.BJSON.ToObject(Byte[] json, Type type) in v1.8.3\RaptorDB.Common\fastBinaryJSON\BJSON.cs:line 171
at fastBinaryJSON.BJSON.ToObject(Byte[] json) in v1.8.3\RaptorDB.Common\fastBinaryJSON\BJSON.cs:line 149
at RaptorDB.RaptorDB.CreateObject(Byte[] b) in v1.8.3\RaptorDB\RaptorDB.cs:line 464
at RaptorDB.RaptorDB.Fetch(Guid docID) in v1.8.3\RaptorDB\RaptorDB.cs:line 219
After a bit of investigation in appears that it is because the object that I'm retrieving has a property with a public getter and a private setter. Changing this private setter back to being public fixed this issue but I'm trying to see if there is a better way of doing this? I'd prefer to not have to make this setter public.
Some sample code to show the structure of my object. In reality my code is a lot more complicated and the getter has a lot more logic in it so it's not possible to have the setter actually set the value of "property2".
public class Sample
{
public string property1;
private string _property2;
public string property2
{
get
{
return _property2;
}
private set
{
}
}
public Sample(string initProp)
{
_property2 = prop;
}
}
I get the error with the code above when I try to retrieve an object of type Sample. If I change the line "private set" to "set" then I can retrieve objects of type sample.
Thanks in advance for the help.
|
|
|
|

|
It's a requirement of fastJSON and fastBinaryJSON that your objects have:
1.A default constructor (without parameters)
2.If you want to deserialize back to the original have a public Set for your properties.
You can use XmlIgnore on properties to exclude from the serialization process, and the default is also to ignore readonly properties.
Hope that helps.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
XmlIgnore is exactly what I'm looking for. Thanks for the help
|
|
|
|

|
What are the chances a shared hosting provider is going to have this?
-MickeyB
|
|
|
|

|
I don't see any reason why not especially since it does not have any dependancies other than .net.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
I guess if you control the file/folder location you may pull it off. Will give this a try out on Brinkster soon.
-MickeyB
|
|
|
|

|
It would certainly be an interesting experiment!
Keep me posted on how you get along, Mickey!
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|
|

|
Thanks Michael!
Full text search exists in the views.
The feature you are referring to is a full text search on the complete document which is a work in progress at the moment.
To use full text in the views all you need to do is put the [FullText] attribute on your schema column in the view definition. To query you need to use the = operator and follow the lucene style querying convention. Contains is not supported in linq queries.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Ahhhhh, I see. Thanks for the clarification. I'll give it a go
|
|
|
|

|
Mehdi, Thanks for update 1.83. Is it possible to use the FullText attribute with a string field that consists of a single word? I get an IndexOutOfRange exception when I try to do so. For example, can a search of a forename field using Jo* return John, Joe etc?
|
|
|
|

|
It should work, I will look into why it doesn't, thanks George!
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Mehdi, Thanks for your help, I’ve reinstalled everything and it is now returning results. But, for example, a search for “Sw*” returns Wordsworth as well as Swift.
|
|
|
|

|
Edit the following line in hoot.cs ln176
Regex reg = new Regex(s.Replace("*", ".*").Replace("?", "."), RegexOptions.IgnoreCase); to Regex reg = new Regex("^"+s.Replace("*", ".*").Replace("?", "."), RegexOptions.IgnoreCase);
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|
|

|
Hi Mehdi.
I do not want to bore you. Sorry.
One of the most common operation using a storage system is to count objects/records that meet certain criteria or more simply to get a total count of objects present.
Your StorageFile's performances are very impressive but obviously deserializing object it's time and resources consuming.
In order to get a simple count of a very large set of object ViewHandler.Query method still creates a full populed list of objects. To get a count of milions object store could be very slow, could consume a very great qty of memory and only to get a simply "2,000,000 of record are presents" message.
If I can I'd like to submit to you a possible solution to lazyload data mantaining a fully backward compatible interface for the clients.
Obviously this is only one of the possible solutions ad a bit of additional work has to be done in order to be sure to make consistent the ViewHandler object state since data are loaded from the client.
The solution consist of a new class to be able to define a typed lazyload object (In this case I preferred to non use the System.Lazy class in order to have the complete control for implicit casting):
public class LazyLoader<T>
{
T value;
Func<T> loader;
public LazyLoader(T value) { this.value = value; }
public LazyLoader(Func<T> loader) { this.loader = loader; }
T Value
{
get
{
if (loader != null)
{
value = loader();
loader = null;
}
return value;
}
}
public static implicit operator T(LazyLoader<T> lazy)
{
return lazy.Value;
}
public static implicit operator LazyLoader<T>(T value)
{
return new LazyLoader<T>(value);
}
}
Result class changed as below
public class Result
{
private LazyLoader<List<object>> lazyRows = null;
public Result()
{
}
public Result(bool ok)
{
OK = ok;
}
public Result(bool ok, Exception ex)
{
OK = ok;
EX = ex;
}
/// <summary>
/// T=Values return, F=exceptions occurred
/// </summary>
public bool OK { get; set; }
public Exception EX { get; set; }
/// <summary>
/// Total number of rows of the query
/// </summary>
public int TotalCount { get; set; }
/// <summary>
/// Rows returned
/// </summary>
public int Count { get; set; }
public void SetLazyRows(LazyLoader<List<object>>
lazyResultRows)
{
this.lazyRows = lazyResultRows;
}
public List<object> Rows
{
get
{
return lazyRows;
}
set
{
this.lazyRows = new LazyLoader<List<object>> (value);
}
}
// FEATURE : data pending in results
///// <summary>
///// Data is being indexed, so results will not reflect
all documents
///// </summary>
//public bool DataPending { get; set; }
}
Some changes in Query e ReturnRows methods of ViewHandler class and a new Global variable to indicate if to use or not lazy loading... It's a bit frustrating to write code using this editor so if you 'd like to discuss about the matter we can choose an'other way to comunicate.
Thanks for your attention
Antonello
|
|
|
|

|
Lazy loading will only make sense when in embedded mode, in server mode the engine will generate and send the data anyway (it would be very difficult to implement over tcp).
However "paging" is a feature which I will put in soon.
As for counting, that is easy as all that needs to be doe is count the query result bits e.g.:
int count = rap.Count(typeof(view), (view s) => c.column >10);
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Thank you very much Mehdi.
I completely agree with you on the lazy loading usefulness only for the embedded mode.
A "must to have" the next introduction of paging !!!
int count = rap.Count(typeof(view), (view s) => c.column >10);
It's already available ? I cannot find that method.
Best Regards,
Antonello
|
|
|
|

|
The count method is a proposal (it is not currently implemented).
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Inserting a large amount of data RabptorDB.FileLogger.Log method returns an "Source array was not long enough".
This could be caused by a bad access to to the _que member. To enque data in Queue the usafe code Array.Copy is used. in case of concurrent access from multiple threads to _que it's possible to get that kind of exception.
A possible solution could consist of lock the _que member directly instead of using different objects (_lock, _writelock) to syncronize access.
Below one possible solution to apply to FileLogger class methods involved.
Obviously it has to be evalued as valid.
public void Log(string logtype, string type, string meth, string msg, params object[] objs)
{
lock(_que) _que.Enqueue(FormatLog(logtype, type, meth, msg, objs));
}
private void WriteData()
{
if (_output == null)
return;
lock(_que) {
..
..
..
..
}
}
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
NoSql, JSON based, Document store database with compiled .net map functions and automatic hybrid bitmap indexing and LINQ query filters (now with standalone Server mode, Backup and Active Restore, Transactions, Server side queries, MonoDroid support)
| Type | Article |
| Licence | CPOL |
| First Posted | 29 Apr 2012 |
| Views | 157,465 |
| Downloads | 5,235 |
| Bookmarked | 227 times |
|
|