I've got a SQL Server database that I'm trying to build a RESTful API for.
I'm using ADO.Net and Linq to retrieve a single row from a table like this:
[HttpGet]
public tTrip getTripById(Guid id)
{
var _trip = (from trips in db.tTrip
where trips.ID == id
select trips).FirstOrDefault();
return _trip;
}
When I debug the code the correct object is retrieved. If I keep running however, there will be no response. I'm guessing that's because for every foreign key present in the returned row, ADO does another lookup through the other mapped tables which slows down everything by a lot.
If I only select a single column that doesn't contain any FKCs everything works fine.
Any ideas how I can turn off the FKC lookup for that fetched object?
Thank you!
I found the problem - In the ObjectContext class (that's where the 'db' variable comes from btw), I had the ContextOptions.LazyLoadingEnabled variable set to true.
Set it to false and the application returns only the Guid for every entry instead of loading the entry details from the database.
Related
This is a bit of a puzzle I'm trying to figure out.
I am working on a system where we have a number of company records saved in the database. Some of these records are duplicates and are no longer wanted/required.
However, several external systems are still mapping to these invalid records. If we were to delete them entirely it would cause errors to the systems still wanting to get the detail of that company.
The ideal workflow I would like would be;
The external system looks up Company ID X.
The current system has a table which has a record of all the remapped records, so when the request comes in, the table specifies to redirect Company ID X to Company ID Y.
There are a number of endpoints that could be altered one-by-one to do this - but it would be time-consuming, resulting in lots of repetition too.
My question is, using Entity Framework and .Net - is there a smart way of achieving this workflow?
My initial thoughts were to do something with the constructor for the company object, which repopulates the object from EF if a 'redirect' exists, but I don't know if this will play nice with navigation properties.
Would anyone have an idea?
Thanks very much.
You can create a column with foreign key for the same table to express the single unique valid company.
For example, you can add DuplicateOf column:
ALTER TABLE [Company]
ADD COLUMN [DuplicateOf] bigint NULL,
FOREIGN KEY [DuplicateOf] REFERENCES [Company] ([Id]);
and express this relation in your code:
public class Company
{
// ...
public Company DuplicateOf { get; set; }
// May be useful, hides check for duplicate logic:
public bool IsDuplicate => DuplicateOf != null;
// May be useful as well,
// returns the non-duplicate uniue company, not a duplicate, either linked or current:
public Company EffectiveCompany => DuplicateOf ?? this;
}
You will have to address EffectiveCompany when you want to work with non-duplicate and maintain this column to always point to the correct record. It will also result into additional query, if eager-loaded.
Another idea is to have a stored procedure GetCompany(bigint id) which will return the effective record - if DuplicateOf exists, or record itself otherwise. It will be good for your external systems and will let you hide all this stuff behind abstraction layer of stored procedure. If you decide to change it in future, then you can easily update it without breaking external systems.
However, for you it isn't always convenient to work with stored procedures with EF.
These are just ideas and not the best solutions, anyway.
In my opinion, the best solution would be to get rid of duplicates, update data everywhere and forget forever about this mess of duplicated data.
I am new to Google Cloud Datastore (NoSQL db). I am developing a web application in C# for which I have successfully configured authentication for google Datastore API by setting GOOGLE_APPLICATION_CREDENTIALS.
I am also able to insert data (entities) in the Datastore kind (I think "kind" refers to tables in Google). However, I am unable to retrieve entities based on retrieval, for example, I want to retrieve entities from Datastore, from a kind named "Task" where a column named "word" has the word "hello" in it.
I would also like to know whether I can keep a column which has a datatype of "string" as key column (like a primary key column in SQL database tables). I also need help as to how I can update a column/property for a particular entity.
string projectId = "xyz";
DatastoreDb db = DatastoreDb.Create(projectId);
Query query = new Query("Task")
{
Filter = Filter.Equal("word", "hello")
};
DatastoreQueryResults dres = db.RunQuery(query);
First of all, a kind in Cloud Datastore is indeed the equivalent of a table in SQL. Apart from that, each entity has a unique identifier which includes a key name string and a numeric ID (integer).
If you want to retrieve a particular entity, you can use the Lookup function based on the key of that entity, like this:
Entity task = _db.Lookup(_sampleTask.Key);
This also applies if you want to retrieve multiple entities:
var keys = new Key[] { _keyFactory.CreateKey(1), _keyFactory.CreateKey(2) };
var tasks = _db.Lookup(keys[0], keys[1]);
For updating a particular entity, you can modify its properties and then store it using the same key it had before:
_sampleTask["priority"] = 5;
_db.Update(_sampleTask);
This link can be quite useful to understand how to use Cloud Datastore with .NET and C#. It includes a tutorial for building a bookshelf based in Datastore and deploying it in App Engine.
As for what to use as a key, Datastore uses an ancestor structure, just like a file system directory. One entity can be set as the child of another, that becomes its parent, and this can continue until a full structure is created with ancestors and children.
This is an example of a key from an entity which has ancestors:
[User:alice, TaskList:default, Task:sampleTask]
This is the key of a root entity, which has no parents:
[User:alice]
For more info about the ancestor paths, check this link.
In GCP Web Console, you can run queries directly in sql, from there you can do a quick test if the query is returning expected results.
Datastore requires indexes to be crated before you can query on them, from web console when you run the query, you will know more about it.
If you see results on web console, but not able to retrieve when queries programmatically, you can check GCP logs for any exceptions to debug the issue.
I am using EF6 to create and populate a table with its primary key as a ServerTime (DateTime).
The table is very large, and in order to speed up access times as well as enjoy the benefit of having my table split into smaller partition files instead of one massive .ibd file when I perform an external query such as this:
SELECT
gbpusd.servertime,
gbpusd.orderbook
FROM
gbpusd
WHERE
gbpusd.servertime BETWEEN '2014-12-23 23:48:08.183000' AND '2015-03-23 23:48:08.183000'
I would like the table to be automatically partitioned by servertime during Code First creation.
I already know the raw MySql syntax for partitioning a table by range.
My current solution is to create and populate the database via EF6 Code first, and then manually execute the partitioning via raw MySQL query. Another solution is to use plain old ADO.NET directly after Code First creation, but I would have rather have everything streamlined inside EF6 code.
What I need to know is how I can accomplish the same thing via Code First implementation (assuming it is even possible)
Much thanks.
Is it about only speed up ? Where you need to populate this data? Assuming you have service layer or manager to use this entity.You can always use use your repository to perform over your entity using lembda expression.
example
using (var dataBaseContext= new your_DbContext())
{
var repoServer = new Repository<gbpusd>(dataBaseContext);
var searchedGbpusd =repoServer.SearchFor(i=> i.servertime <= date && i.servertime >= date).select;
///you can specify date what ever you like
///use this searched Data where ever you want to use.
}
Hope it will help.
Thanks
Fahad
You can just create your entity using EF6 code first practice. Using search via repository practice search the data and fill in that table. Like I suggested , use searched data and then fill the data and run this activity as frequently as you need. Like can do when users are not on peak. – Shaikh Muhammad Fahad 1
My azure storage table's Row key is set as a GUID. Am not able to query the entity for some specific GUID's or it could be happening randomly. But for some GUID's however number of queries i make, it doesnt return the entity but i can clearly see the record in the table. I have no clue why thats happening. Could it be because am using different data service contexts for creating the entity and fetching the entity using the GUID. Below is the simple code snippet.
TableStorageServiceContext<PersistedAudioRecord> audioRecordServiceContext;
audioRecordServiceContext = new TableStorageServiceContext<PersistedAudioRecord>(TableNames.AudioRecord, cloudStorageAccount.TableEndpoint.ToString(), cloudStorageAccount.Credentials) { IgnoreResourceNotFoundException = true };
return audioRecordServiceContext.QueryableEntities.Where(b => b.RowKey == id).FirstOrDefault();
I have been banging my head about this issue, any ideas or suggestions are deeply appreciated.
Thanks
I see that you're querying using just RowKey. This may result in full table scan and table service will only return a maximum of 1000 entities / request. If the table service encounters a Partition Boundary, it may return 0 entities. Can you please check when you don't get the data, you're getting a continuation token? You can check that using a tool like Fiddler.
I have a multi-page (multi-view) form in MVC, the results of which will be saved to a single database table.
Code snippet that initializes the linq object in the first page of the form.
public ActionResult MyForm()
{
// returns a Linq object stored in session
Application currentApp = Application.FromSession();
// if null, initialize the object and save to session
if (currentApp == null)
{
currentApp = new Application();
currentApp.SessionSave();
}
return View(currentApp);
}
And here is a sample snippet of code for the final action that updates some data from the strongly-typed model, then triggers the database save.
[HttpPost]
public ActionResult MyForm3(Application app, FormCollection coll)
{
Application currentApp = Application.FromSession();
currentApp.Contact = app.Contact;
currentApp.AddFormToXml(coll);
currentApp.SessionSave();
_db.Applications.InsertOnSubmit(currentApp);
_db.SubmitChanges();
return RedirectToAction("Blah");
}
The problem I'm running into is that the SubmitChanges fails with the error
Cannot insert the value NULL into
column 'ApplicationData', table
'MyTable';
column does not allow nulls. INSERT
fails. The statement has been
terminated.
In this case, ApplicationData is a column of type xml, which LINQ interprets as an XElement object. When I set a breakpoint at SubmitChanges() and check the value of app.ApplicationData, it is clearly populated (non-null), and yet I continue to get this error. My only thought is that I am misunderstanding something with how data contexts work. It only seems to have an issue with this one column though. Is it possible that I need to figure out a way to attach the XElement object (ApplicationData) to my active data context (_db), and if so, how would I go about doing that?
Take a look at the actual SQL generated and sent to the server.
Start up SQL Server Profiler (on the tools menu in SQL Server Management Studio) and start a trace. Run your application until it crashes. Go back to SQL profiler and look at the SQL queries. Seeing things from the SQL end sometimes make it easy to spot the error, e.g. finding out if your are doing several inserts instead of just one.
Well my suggestion to you is to compare the data type of "ApplicationData" column in your Context model and in your database table.
Also please check your LINQ to SQL mappings for this column "AppliationData" again on the datatype itself.
Please update your post if you find anything...
Ok, so in the action method you mentioned can you check if you are calling the InsertOnSumbit Method again anywhere else before you are finally calling db.SubmitChanges()...or if you are calling the InsertOnSubmit method more than once... I think that will cause a problem if you are calling it twice on the same object.
Update:
I did tried a sample with a single table and was able to insert the xml data as mentioned below.
DataClassesDataContext ctx = new DataClassesDataContext();
Application a1 = new Application();
XName n = "dfdsf";
a1.ApplicationData = new XElement(n);
ctx.Applications.InsertOnSubmit(a1);
ctx.SubmitChanges();
so, now the question will be what does your column data looks like??? if you can post the sample content of the application data then it will be helpful. Also how are you setting the ApplicationData property value?