PersistentComponentState size limit - persistence

I use PersistentComponentState to keep data after prerendering.
[Inject] PersistentComponentState ApplicationState { get; set; }
by saving it:
ApplicationState.PersistAsJson("documents", docs);
and then read it:
if (ApplicationState.TryTakeFromJson<Documents>("documents", out var stored))
docs = stored;
But if I have big enough list of documents TryTakeFromJson return false.
Question: is there limit for PersistentComponentState and can I increase it?

Related

When to use Include in EF? Not needed in projection?

I have the following in Entity Framework Core:
public class Book {
public Int32 Id { get; set; }
public String Title { get; set; }
public virtual Theme Theme { get; set; }
}
public class Theme {
public Int32 Id { get; set; }
public String Name { get; set; }
public Byte[] Illustration { get; set; }
public virtual ICollection<Ebook> Ebooks { get; set; }
}
And I have the following linq query:
List<BookModel> books = await context.Books.Select(x =>
new BookModel {
Id = x.Id,
Name = x.Name,
Theme = new ThemeModel {
Id = x.Theme.Id,
Name = x.Theme.Name
}
}).ToListAsync();
I didn't need to include the Theme to make this work, e.g:
List<BookModel> books = await context.Books.Include(x => x.Theme).Select(x => ...
When will I need to use Include in Entity Framework?
UPDATE
I added a column of type Byte[] Illustration in Theme. In my projection I am not including that column so will it be loaded if I use Include? Or is never loaded unless I have it in the projection?
In search for an official answer to your question from Microsoft's side, I found this quote from Diego Vega (part of the Entity Framework and .NET team) made at the aspnet/Announcements github
repository:
A very common issue we see when looking at user LINQ queries is the use of Include() where it is unnecessary and cannot be honored. The typical pattern usually looks something like this:
var pids = context.Orders
.Include(o => o.Product)
.Where(o => o.Product.Name == "Baked Beans")
.Select(o =>o.ProductId)
.ToList();
One might assume that the Include operation here is required because of the reference to the Product navigation property in the Where and Select operations. However, in EF Core, these two things are orthogonal: Include controls which navigation properties are loaded in entities returned in the final results, and our LINQ translator can directly translate expressions involving navigation properties.
You didn't need Include because you were working inside EF context. When you reference Theme inside the anonymous object you are creating, that's not using lazy loading, that's telling EF to do a join.
If you return a list of books and you don't include the themes, then when you try to get the theme you'll notice that it's null. If the EF connection is open and you have lazy loading, it will go to the DB and grab it for you. But, if the connection is not opened, then you have to get it explicitely.
On the other hand, if you use Include, you get the data right away. Under the hood it's gonna do a JOIN to the necessary table and get the data right there.
You can check the SQL query that EF is generating for you and that's gonna make things clearer for you. You'll see only one SQL query.
If you Include a child, it is loaded as part of the original query, which makes it larger.
If you don't Include or reference the child in some other way in the query, the initial resultset is smaller, but each child you later reference will lazy load through a new request to the database.
If you loop through 1000 users in one request and then ask for their 10 photos each, you will make 1001 database requests if you don't Include the child...
Also, lazy loading requires the context hasn't been disposed. Always an unpleasant surprise when you pass an Entity to a view for UI rendering for example.
update
Try this for example and see it fail:
var book = await context.Books.First();
var theme = book.Theme;
Then try this:
var book = await context.Books.Include(b => b.Theme).First();
var theme = book.Theme;

Entity Framework field query slow

I'm having some trouble working with a particular ef query. I've simplified everything down as much as I can. I'm only querying for two columns. Here is my model.
[Table("TAXROLL", Schema = "CLAND")]
public class TaxRoll
{
[Key]
[Column("TAXROLL_ID")]
public string Id { get; set; }
[Column("APN")]
public string APN { get; set; }
}
When I execute my query in my controller, if I do firstordefault, the results take as long as 15-18 seconds to return. If I do a where query, the results are almost instantaneous (less than 1 second), (see my commented timing statements below. When I say 15-18 seconds and almost instantaneous, that's where my numbers are coming from).
[ResponseType(typeof(TaxRoll))]
public async Task<IHttpActionResult> Get(string id)
{
//var start = DateTime.Now;
//Debug.WriteLine("Starting Query");
var apnRecord = await ctx.TaxRoll.FirstOrDefaultAsync(x => x.APN == id);
//Debug.WriteLine("Returning APN after " + DateTime.Now.Subtract(start).TotalSeconds);
return Ok(apnRecord);
}
When I query for the primary key (Id), results return consistently fast every single time regardless of how I run the query. This is only a problem when I'm querying for APN. Yes, APN is indexed. It's also unique. I could use it as PK, and in fact I tried that. No dice. I know that executing a query that searches based on APN consistently returns fast when I do it directly against the database.
Any help or direction is greatly appreciated -- I am thoroughly confused.
Your APN Column is NULLABLE that makes EF add OR operator, 99% it makes SQL to "seek" the column (which does not use index). make APN column NOT NULL.
Additionally to the user skalinkin answer, you can set DbContextConfiguration.UseDatabaseNullSemantics property to true.
public class YourDbContext : DbContext
{
public YourDbContext()
{
Configuration.UseDatabaseNullSemantics = true;
// ...
}
}
The query that takes 15-18s
var apnRecord = await ctx.TaxRoll.FirstOrDefaultAsync(x => x.APN == id);
Is same as
var apnRecord = await ctx.TaxRoll.Where(x => x.APN == id).FirstOrDefaultAsync();
If you are using just Where(), nothing will be materialized from the database.
Also consider using Stopwatch instead of calculating timestamps.
var sw = new Stopwatch();
sw.Start();
// do something
Debug.WriteLine(sw.Elapsed);

How/When Sql server updates the record timestamp value, if I have a transaction with multiple CRUD operations

I am working on an asp.net mvc web application and I am using an entity framework to map my tables into model classes.
I have the model class representing VMS:-
public partial class TMSVirtualMachine
{
public int TMSVirtualMachineID { get; set; }
public int ServerID { get; set; }
public int RoleID { get; set; }
public Nullable<int> BackUpStatusID { get; set; }
public Nullable<int> StatusID { get; set; }
public Nullable<int> MonitoreID { get; set; }
public Nullable<decimal> TotalStorage { get; set; }
public string Comment { get; set; }
public byte[] timestamp { get; set; }
public Nullable<long> IT360SiteID { get; set; }
public virtual TMSServer TMSServer { get; set; }
//cde goes hereā€¦
}
And I have the following repository method , which will move all the current server;s VMS to another server, by changing the VM's ServerID as follow:-
public int changeVMsServer(AssignVMsToServer s, string username)
{
int count = 0;
var currentvms = tms.TMSVirtualMachines.Where(a => a.ServerID == s.serverIDForm);
foreach (var v in currentvms)
{
v.ServerID = s.serverIDTo;
tms.Entry(v).State = EntityState.Modified;
count++;
}
SaveChanges();
return count;
}
Currently if two users call the above method at the same time one of them will get a DBUpdateConcurrentException, since the timestamp for a VM when trying to save it, will be different than when the VM was retrieved.
My question is basically how SQL server 2008 r2 manage the timestamp column. Let take the following scenario:-
First user retrieve 5 VMs, then generate 5 SQL update commands and save.
Second user retrieve 5 VMs, then generate 5 SQL update , and when trying to save , EF will detect that the timestamp has been changed for atleast one VM and raise a DBUPdateException.
Now when the first user perform the 5 SQL updates operation , his work will not be saved until the 5 update operation successed , since the 5 update operations are wrapped in a single trancaction.
Q1) So when will sql server 2008 r2 changed the timestamp column for the 5 servers , when the transaction is completed ?, or when a single update operation is saved ?, and if the transaction failed will sql server return the old timestamp value ?
Sorry for the long email, but I tried searching for a clear answer , but could not reach a final conclusion.
MSDN documentation on timestamp is quite clear:
Is a data type that exposes automatically generated, unique binary numbers within a database. timestamp is generally used as a mechanism for version-stamping table rows. The storage size is 8 bytes. The timestamp data type is just an incrementing number and does not preserve a date or a time. To record a date or time, use a datetime data type.
...
You can use the timestamp column of a row to easily determine whether any value in the row has changed since the last time it was read. If any change is made to the row, the timestamp value is updated.
So, it's clear that the timestamp is modified when the row changes.
EF will use this column for concurrency checking: if an app reads a row, modifies it and try to save the changes in the DB and the timestamp changed since it was read, then the concurrency exception is thrown.
As to the transaction, what you're missing is the "transaction isolation" concept. The timestamp column changes when a change is made to the row. But what happens if a different connection tries to read this row depends on the isolation level: the row can be locked until the transaction finishes (so the other connection will have to wait until that moment), or the other connection can read the new uncomitted value or it can read the old value. It depends on the isolation level.
By default in SQL Server the isolation level is:
READ COMMITTED
Specifies that statements cannot read data that has been modified but not committed by other transactions. This prevents dirty reads. Data can be changed by other transactions between individual statements within the current transaction, resulting in nonrepeatable reads or phantom data. This option is the SQL Server default.

how to avoid creating entities for returning small data from database

Oftentimes I need to return a list of two or three columns from a stored proc in the data layer. I usually use entities to push data back to the business/UI layer. However, I don't want to create an entity for something that is not really an entity.
Lets say I have to return a set of "date, string, string", is there any other way to do this.. for two columns, i can perhaps get away with a dictionary. I always end up creating a dummy entity but thought I'll ask this time.
Create a new model to store the data:
public class ResultModel
{
public DateTime DateTime1 { get; set; }
public string String1 { get; set; }
public string String1 { get; set; }
}
then just store your data into this like so:
IEnumerable<ResultModel> results =
Entities.Table.Select(r => new ResultModel
{
DateTime1 = r.DateTime,
String1 = r.String1,
String2 = r.String2
});
Not verified the code but is a guide as to how to achieve this.
You could probably use a Tuple for this kind of data however I've never found any real detriment to creating more understandable types, even for simple data.

Building a flexible parameterized adhoc query with C#, SQL

I'm in the process of building the capability for a user to perform ad-hoc queries on a SQL Server database. The resulting query will take on the following basic form:
SELECT <ONE TO MANY USER SELECTED FIELDS>
FROM <ONE TO MANY TABLES DETERMINED BY FIELDS SELECTED BY USER>
WHERE <ZERO TO MANY CRITERIA FOR THE SELECTED FIELDS>
It's a guarantee that the selection will most likely span more than one table.
Some (not all) of the fields may have 0 or more filter criteria for a particular field.
My application is using the default EF4 classes within ASP.NET MVC 2 using C#. I am currently passing in an object called QueryItem that contains all the information for a particular criteria.
My question(s) are:
What is the best approach for coding this? (Code samples of what I have to date below).
Can this be done with Linq2SQL or should I use ADO.NET(My current approach)
If ADO.NET is the best way, how do you access the DBConnection within EF4?
Note: I intend to refactor this into SQLParameter objects, to protect against SQL injection. My goal right now is best practice in developing the query first.
QueryItem class:
public class QueryItem
{
public bool IsIncluded { get; set; }
public bool IsRequired { get; set; }
public string LabelText { get; set; }
public string DatabaseLoc { get; set; }
public List<string> SelectedValue { get; set; }
public List<SelectListItem> SelectList { get; set; }
}
Query Parsing Code
foreach(QueryItem qi in viewModel.StandardQueryItems)
{
string[] dLoc = qi.DatabaseLoc.Split(new Char[] { '.' }); //Split the table.fieldname value into a string array
if(qi.IsIncluded == true) //Check if the field is marked for inclusion in the final query
{
fields.Append(qi.DatabaseLoc + ","); //Append table.fieldname to SELECT statement
if(!tables.ToString().Contains(dLoc[0])) // Confirm that the table name has not already been added to the FROM statement
{
tables.Append(dLoc[0] + ","); //Append the table value to the FROM statement
}
}
if(qi.SelectedValue != null)
{
if(qi.SelectedValue.Count == 1)
{
query.Append(qi.DatabaseLoc + " = '" + qi.SelectedValue[0].ToString() + "'");
}
else
{
foreach(string s in qi.SelectedValue)
{
//Needs to handle "IN" case properly
query.Append(qi.DatabaseLoc + " IN " + qi.SelectedValue.ToString());
}
}
}
}
I have built a similar system to what you are describing in the past by passing in a single parameter to a stored procedure of type xml. By doing so, you can actually specify(in xml), what all you would like to report off of and build the SQL necessary to return the results you want.
This also makes your C# code easier, as all you have to do is generate some xml that your procedure will read. Generating Dynamic SQL is definitely not something you should use unless you have to, but when you want to allow users to dynamically select what they want to report off of, it's pretty much the only way to go about doing it.
Another option for you might be to look into Reporting Services - that will allow the user to pick what fields they want to view and save that particular 'report' in their own section where they can then go back and run it again at any time.. You could also create the reports for them if they aren't computer savvy(which is a lot easier to do with report builder, provided that all they need is data and no special features).
Either way you go about it, their are pros and cons to both solutions.. You'll have to determine which option is best for you.
xml/dynamic sql: Hard to maintain/make changes to.(I feel sorry for anyone who has to come behind someone who is generating dynamic sql and try to understand the logic behind the mess).
reporting services: very easy to spit out reports that look good, but it's a little less flexible and it's not free.