How to add a couple of million documents to RavenDB - Embedded - ravendb

I have installed the latest embedded binaries from NuGet and am using this code to store a 'product' poco. After a bit, the process dies with an OutOfMemoryException. Is storing this much data out of scope for Raven?
Thank you.
Stephen
var store = new EmbeddableDocumentStore { DataDirectory = #"C:\temp\ravendata", UseEmbeddedHttpServer = true };
store.Initialize();
using (var session = store.OpenSession())
{
foreach (var item in Parsers.GetProducts().ToList())
{
session.Store(item);
}
session.SaveChanges();
//var rdbList = session.Query<Product>().ToList();
}
[Serializable]
public class Product
{
public decimal ProductId { get; set; }
public string ItemNum { get; set; }
public string ProductName { get; set; }
public string BrandName { get; set; }
public string UOM { get; set; }
public string AveWeight { get; set; }
public string CasePack { get; set; }
public string PackageRemarks { get; set; }
public decimal Price { get; set; }
public string SupplierName { get; set; }
public string Url { get; set; }
public bool IsSpecialOrderItem { get; set; }
public bool IsSpecialPriceItem { get; set; }
public bool IsRebateItem { get; set; }
public bool IsTieredPricingItem { get; set; }
public bool IsOfflineSupplierItem { get; set; }
public string Catalog { get; set; }
public decimal CatalogId { get; set; }
public decimal CategoryId { get; set; }
public decimal PriceGroupId { get; set; }
public decimal OffineSupplierId { get; set; }
public string ManufactureName { get; set; }
public string ManufactureNum { get; set; }
public string Upc { get; set; }
public string Info { get; set; }
public string INFO2 { get; set; }
}

How big of a batch are you doing? It looks like people have success with 256 batch sizes. Seems like much more causes timeouts and memory exceptions.
*EDIT: It sounds like it is also recommended to make a new session per batch so as to not keep the session open too long which can cause timeout errors.

No, RavenDB is perfectly fine with this amount of data. Unless you don't RunInMemory an EmbeddedDocumentStore is pretty much the same as a standalone server, just without the http overhead and direct access to the database from the client.
Given your code, you want to make sure that you store your documents in batches, e.g. 1024 for each session. Another thing you want to make sure is, that your GetProducts() method returns an IEnumerable and yields the items in a proper ETL way of doing things.

Related

Podio API - Groupings are missing from Views in C#

I am working with the Podio api in C# and "Groupings" is missing from the View and ViewCreateUpdateRequest model.
When I use the sandbox call the result includes the groupings. So I'm thinking it is missing in the C# nuget package. Is there another way to access groupings for both Get View and Update View?
Sadly they are not maintaining the SDK for C#, but you can download their code from https://github.com/podio/podio-dotnet and update the code yourself.
That's what I did, I change the following
ItemId data type from Integer to Long
Added Groupings in View (Below is my View looks like)
public class View
{
[JsonProperty("view_id")]
public string ViewId { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("created_on")]
public DateTime CreatedOn { get; set; }
[JsonProperty("sort_by")]
public string SortBy { get; set; }
[JsonProperty("sort_desc")]
public string SortDesc { get; set; }
[JsonProperty("filters")]
public JArray Filters { get; set; }
[JsonProperty("fields")]
public JObject Fields { get; set; }
[JsonProperty("groupings")]
public JObject Groupings { get; set; }
[JsonProperty("created_by")]
public ByLine CreatedBy { get; set; }
[JsonProperty("layout")]
public string Layout { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("rights")]
public string[] Rights { get; set; }
[JsonProperty("filter_id")]
public string FilterId { get; set; }
[JsonProperty("items")]
public int Items { get; set; }
}
Search for NuGet Package: Podio.Async by acl2

When including other entities other lists are loaded too which leads into a recursion, how can i prevent this?

I have a big database in the background storing:
public partial class Phone
{
public string Imei { get; set; }
public int ColourId { get; set; }
public int StorageId { get; set; }
public int TypeId { get; set; }
public int ModelId { get; set; }
public int PurchasePrice { get; set; }
public DateTime? SaleDate { get; set; }
public DateTime? RentalStart { get; set; }
public DateTime? RentalFinish { get; set; }
public virtual Colour Colour { get; set; }
public virtual Storage Storage { get; set; }
public virtual Type Type { get; set; }
}
public partial class Storage
{
public Storage()
{
Phone = new HashSet<Phone>();
}
public int StorageId { get; set; }
public string Amount { get; set; }
public virtual ICollection<Phone> Phone { get; set; }
}
And I am requesting for the Phone Data like this in my WebAPI:
[HttpGet]
// GET: Phones
public async Task<IActionResult> Index()
{
var phoneCalculatorContext = _context.Phone.Include(p =>
p.Colour).Include(p => p.Storage).Include(p => p.Type);
return Ok(await phoneCalculatorContext.Take(10).ToListAsync());
}
I have posted the JSON Response here:
https://textuploader.com/1dtu2
As you can see in my response is storage included (as expected) but storage has a reference to my Phone Collection and this goes on and on and on (like an recursion)
Is it possible to not get the lists?
Because I dont need the lists I just need to get the amount of storage but not the pone list.
Sorry for the poor understanding of EF but I am pretty new to this.
If you don't need that an storage know in how many phones it's, you can remove the ICollection property.
other solution is mark the phones property in storage as this
[JsonIgnore]
public virtual ICollection<Phone> Phone { get; set; }
For disabling self reference serialize, you could try SerializerSettings.ReferenceLoopHandling like
services.AddMvc()
.AddJsonOptions(opt => {
opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

ASP.NET MVC ViewModel is null on Post Back - sometimes

depending on my input in an HTML form (6 or 6.5 - or in general, integer VS float) I get or don't get the following exception (it works with int and doesn't work with float):
The model item passed into the dictionary is null, but this dictionary requires a non-null model item of type 'System.Boolean'.
The ViewModel of my View is null and the problem gets visible in a custom template which expects a bool value, but gets null instead. We use ASP.NET MVC 4 with .Net 4.0, C# and Razor Templates.
After several hours debugging I came to the following conclusion(s):
Post Form-Data are identical (except the one property which is different, but still look correct)
The execution order is somehow weirdly different:
for int I get Application_BeginRequest->Filter which runs through my attributes->Action->View Rendering OR Redirect (everything Normal)
for float I get Application_BeginRequest->Filter which runs through my attributes->View Rendering->END WITH AN EXCEPTION and Empty ViewModel
I have checked it dozen times -> If I pass float the View somehow gets rendered without any Action (which I would have seen) to be executed (and of course the breakpoints were the same all the time). Unfortunately I couldn't see anything in the StackTrace anymore once the View got rendered.
the ViewModel of my View is:
public class JabCommonViewModel
{
public int JAB_ID { get; set; }
[UIHint("Checkbox")]
public bool JAB_gesperrt { get; set; }
[UIHint("Checkbox")]
public bool JAB_Kontrolliert { get; set; }
public int e001 { get; set; }
public string e002 { get; set; }
public int e005 { get; set; }
[UIHint("Checkbox")]
public bool e013 { get; set; }
public bool e014 { get; set; }
public short? e015 { get; set; }
public bool? e149 { get; set; }
public int? e649 { get; set; }
public int? e310 { get; set; }
public int? LastJabe311 { get; set; }
public int jabIdE013 { get; set; }
public int jabIdPrev { get; set; }
public int updCnt { get; set; }
public int checks { get; set; }
public bool calculateInEur { get; set; }
public FormViewModel AktivaPassiva { get; set; }
public FormViewModel GuV1GuV2 { get; set; }
public FormViewModel GuV3 { get; set; }
public ActsFormViewModel ActsForm { get; set; }
public CommonDataViewModel CommonDataForm { get; set; }
public CompanyHeadViewModel CompanyHeadForm { get; set; }
public FacilitiesOverviewModel FacilitiesOverview { get; set; }
}
public class FormViewModel
{
public string ShowAllCaption { get; set; }
public string HideAllCaption { get; set; }
public string CurrentCaption { get; set; }
public string PreviousCaption { get; set; }
public bool HasPreviousData { get; set; }
public IEnumerable<FieldViewModel> Fields { get; set; }
public FormViewModel()
{
Fields = new FieldViewModel[0];
}
}
public class FieldViewModel
{
public string Name { get; set; }
public string Title { get; set; }
public object Value { get; set; }
public bool IsDisabled { get; set; }
public bool IsCollapsible { get; set; }
public bool IsSpecialCase { get; set; } // used currently to expand/collapse groups on second level
public FieldViewModel Previous { get; set; }
public Category DataCategory { get; set; }
public IEnumerable<FieldViewModel> Related { get; set; }
public FieldViewModel()
{
Related = new FieldViewModel[0];
}
public FieldViewModel(string name, string title, object value, bool isDisabled, Category dataCategory = Category.None, bool isCollapsible = true)
{
Name = name;
Title = title;
Value = value;
IsDisabled = isDisabled;
DataCategory = dataCategory;
IsCollapsible = isCollapsible;
Related = new FieldViewModel[0];
}
}
....
The Post-Back Action is
public ActionResult Edit(JAB2 jab)
{
ComponentFactory.Logger.Debug("Edit with JAB2");
....
}
public class JAB2 : JAB
{
public int jabIdE013 { get; set; }
public JAB LastJab { get; set; }
public int checks { get; set; }
}
public class JAB : BaseModel
{
public JAB()
{
}
public bool e116 { get; set; }
public bool e117 { get; set; }
public bool e118 { get; set; }
public bool e119 { get; set; }
public bool e120 { get; set; }
public bool e121 { get; set; }
public bool e122 { get; set; }
public bool e123 { get; set; }
public bool e124 { get; set; }
public bool e125 { get; set; }
public short? e126 { get; set; }
... /* 100 more properties */ ...
[LocalizedDisplayName("e751", NameResourceType = typeof(Resources.ModelPropertyNames))]
public float? e751 { get; set; } /* the property which works as int but not as float */
}
The Post-Back is actually to the link
/JAB/Edit/
Still the correct method get's executed when e751 (the special property) has an integer value.
Also we use the autoNumeric-JavaScript Plugin on that field. Also we use the plugin with other fields but so far found the error only with this one. As well, we have one Workstation where we aren't able to reproduce the error so it occurs on 2 out of 3 workstations + test server.
So far, nothing I've found explains the fact that it works sometimes.
Thank you very much for taking the time and reading my post.
Do you have any Ideas what could be wrong or what I could check?

Handling document relationships with T[] instead of T using RavenDB

RavenDB docs show how to deal with document relationships in this sample using Includes.
public class Order
{
public Product[] Items { get; set; }
public string CustomerId { get; set; }
public double TotalPrice { get; set; }
}
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public string[] Images { get; set; }
public double Price { get; set; }
}
public class Customer
{
public string Name { get; set; }
public string Address { get; set; }
public short Age { get; set; }
public string HashedPassword { get; set; }
}
How would I deal with Includes or Live Projections if I don't want to include the customer using Includes/Live Projections but a list of products instead:
public class Order
{
public string[] ItemIds { get; set; }
public string CustomerId { get; set; }
public double TotalPrice { get; set; }
}
If I understand what you're asking, this should help. I blogged about it here:
http://inaspiralarray.blogspot.com/2012/03/keeping-domain-model-pure-with-ravendb.html
Does that help?

How do I construct my RavenDb static indexes for this document, given these requirements?

I have close to 3 million documents that are being stored in a RavenDb embedded instance. Everyone of the fields will be subjected to some type of filter/query/sorting, but in particular I wanted to do some type of intelligent textual search of the info and info2 columns. How might I go about constructing the RavenDb Indexes?
My first pass at the info2 column looks like this.
store.DatabaseCommands.PutIndex("ProdcustByInfo2", new IndexDefinitionBuilder<Product>
{
Map = products => from product in products
select new { product.INFO2 },
Indexes = { { x => x.INFO2, FieldIndexing.Analyzed } }
});
Thank you,
Stephen
[Serializable]
public class Product
{
public string AveWeight { get; set; }
public string BrandName { get; set; }
public string CasePack { get; set; }
public string Catalog { get; set; }
public decimal CatalogId { get; set; }
public decimal CategoryId { get; set; }
public string Info { get; set; }
public bool IsOfflineSupplierItem { get; set; }
public bool IsRebateItem { get; set; }
public bool IsSpecialOrderItem { get; set; }
public bool IsSpecialPriceItem { get; set; }
public bool IsTieredPricingItem { get; set; }
public string ItemNum { get; set; }
public string ManufactureName { get; set; }
public string ManufactureNum { get; set; }
public decimal OffineSupplierId { get; set; }
public string PackageRemarks { get; set; }
public decimal Price { get; set; }
public decimal PriceGroupId { get; set; }
public decimal ProductId { get; set; }
public string ProductName { get; set; }
public int Quantity { get; set; }
public string SupplierName { get; set; }
public string UOM { get; set; }
public string Upc { get; set; }
public string Url { get; set; }
}
Spaten,
Create a single RavenDB index, which output all of the properties that you are interested in querying on.
Mark the Info2 and Info as full text search (Analyzed).
You are pretty much done.