I have a Vue PWA and it stopped creating my IndexDB object stores on first load or upgrade. Here is my code, I am using the latest version of IDB (https://github.com/jakearchibald/idb):
await openDB('dbname', 1, {
upgrade(db, oldVersion, newVersion, transaction) {
switch (newVersion) {
case 0:
// a placeholder case so that the switch block will
// execute when the database is first created
// (oldVersion is 0)
// falls through
case 1:
db.createObjectStore('change_log', {keyPath: 'id'});
db.createObjectStore('person', {keyPath: 'id'})
.createIndex('username', 'username');
break;
}
}
});
I have tried multiple browsers and incognito tabs, etc. and the same thing always happens. The database is created, but no object stores are created. I use developer tools to clear all the data in the PWA and refresh but the same thing happens.
If I increment the version number, the version of my database gets updated in the browser, but the object stores still do not get added.
The upgrade() function does not get called.
I had this happen to me earlier in my development, and I fixed it, but I can't remember how. I feel like it may not actually be a coding issue...
OK, I found the problem. I added a logging mechanism to my App and there was code running BEFORE my upgrade code that was opening the database to create a log entry. Therefore, it was creating the database (with no object stores) before my upgrade method was being called. I changed my open database code to always include the upgrade method to solve my problems.
Related
Been using EF Core with Razor pages for a few years now, but Blazor with EF Core has me questioning myself on tasks that used to be simple. I'm creating a golf app, and I'm attempting to update a particular person's round of golf.
Having stumbled in the beginning, I have learned that using dependency injection for the dbContext in Blazor causes several errors including the one in my subject line. Instead, I'm using DI to inject an IDbContextFactory and creating a new context in each method of my services.
The following code updates a golfer's round. When editing, the user may change the course, teebox, or any of the 18 scores. I'm able to update the round once, but if I go back into the same round to edit it a second time I get the "cannot be tracked" "already tracking" error.
I've scoured the internet for possible reasons, I've tried .AsNoTracking() on my initial GetRound(), I've tried detaching the entry after SaveChangesAsync(), I've tried using the ChangeTracker to check whether I need to attach to the Round object being updated. Nothing I've done allows me to update the same round twice without doing a reload in between the first and second update.
I'll provide whatever code necessary, but I'll start with the offending code:
public async Task<bool> UpdateRoundAsync(RoundModel Round)
{
var rtnVal = false;
try
{
using (var _context = _dbFactory.CreateDbContext())
{
_context.Rounds.Attach(Round).State = EntityState.Modified;
await _context.SaveChangesAsync();
_context.Entry(Round).State = EntityState.Detached;
}
rtnVal = true;
}
catch (Exception ex)
{
Console.Write(ex.Message);
throw;
}
return rtnVal;
}
When I run the above code, I see NOTHING in the change tracker as modified until I attach to the Round. Despite nothing being tracked, despite the dbContext being created new, then disposed, I still get an error that I'm already tracking the entity.
Help? What am I doing wrong?
Danny
UPDATE:
Edited the repro as requested, but it did not change the issue - still unable to update the Round twice without a reload in between.
Caveat: I'm not happy posting this as an answer, but it does solve the problem for now. I won't mark it as THE answer until I understand more about EFCore and Blazor together.
I did find that I was making a call to get course details without telling EF that I didn't want it to track the entity, however, that still didn't fix the problem.
In the end, I simply forced the page to reload programmatically: NavMgr.NavigateTo("[same page]", true) after my update call. It feels very un-Blazor-like to do it this way, but ultimately I'm still learning Blazor and not getting much feedback on this post. I'm going to forage ahead, and hope that clarity comes down the road.
For anyone that may run across this post, I ran into the same issue in a completely different project, and finally found something that made sense (here on S/O).
In this line of code:
_context.Rounds.Attach(Round).State = EntityState.Modified;
It should be:
_context.Entry(Round).State = EntityState.Modified;
I never knew that these two were different, and I never had an issue using the first example's syntax before starting to code with Blazor.
If you are unaware, like me, the first way of setting the state to modified updates the entity and all related entities - which is why I was getting the error when I tried to make additional changes to the round-related objects.
The second way of setting the state ONLY updates the entity itself and leaves the related entities in a State of Unchanged.
Thank you to #TwoFingerRightClick for his comment on the accepted answer on this post: Related post
I'm playing with Firebase as an alternative to a local Mongo store, for the time being.
I've followed various tutorials, however they are all for older versions of ES6. I've tried to tweak them to v14 and ES6 but, well, no errors but no data!
Some code:
var Rebase = require('re-base');
var base = Rebase.createClass('https://reactathon.firebaseio.com/days');
...
componentDidMount() {
console.log('ExampleComponent Mounted');
base.bindToState('days', {
context: this,
state: 'days',
asArray: true
});
console.log(this.state.days[0]);
}
The console simply logs undefined. I've tried the base URL with and without /days. I've tried getting the data as an object instead of an array. I have a feeling I'm simply pointing at the wrong thing.
Any thoughts?
Cheers.
bindToState is an asynchronous method so it's going to take some time to set up that listener. You're logging before the listener has been set up. As Jacob mentioned in his comment, move your log to your render method and then once your state is bound to Firebase your component will re render and you should see your data.
Because changed data (inserted by application A) needs to be displayed in application B in realtime we decided to go with .find().observe(...).
It does look like:
App A -> Insert -> mongodb <- observe -> publish -> Display App B
This works fine but it has a delay of about 3-5 seconds between Inserting in A and displaying in B. How can i change this?
Initially i thought, Oplog-Observe-Driver is default in Meteor > Version 1 and does react in realtime. Does it still POLL or is there some other reason for the delay????
Thanks for your expanations.
If you're using Oplog, then the changes will be immediate. If you're using poll then it'll take a few seconds as you wrote.
You need to set MONGO_OPLOG_URL correctly to make this work. (And of course your MongoDB needs to be Oplog enabled.)
Also, you don't need to use find().observe() if you're in a reactive context, find() is enough. On the server though you might need find().observe() depending on what you're doing.
Did you use DDP.connect? You also have to use the onReconnect
Remote = DDP.connect('http://yourremoteserver');
MyCollection = new Mongo.Collection('same_name', Remote);
// do whatever you need with collection
let watchCollection = function (query={}, project={}) {
return MyCollection.find(query, project).observe({
changed: function () { console.log('Something changed!') }
});
}
DDP.onReconnect(watchCollection);
[I am new to ADO.NET and the Entity Framework, so forgive me if this questions seems odd.]
In my WPF application a user can switch between different databases at run time. When they do this I want to be able to do a quick check that the database is still available. What I have easily available is the ObjectContext. The test I am preforming is getting the count on the total records of a very small table and if it returns results then it passed, if I get an exception then it fails. I don't like this test, it seemed the easiest to do with the ObjectContext.
I have tried setting the connection timeout it in the connection string and on the ObjectConntext and either seem to change anything for the first scenario, while the second one is already fast so it isn't noticeable if it changes anything.
Scenario One
If the connect was down when before first access it takes about 30 seconds before it gives me the exception that the underlying provider failed.
Scenario Two
If the database was up when I started the application and I access it, and then the connect drops while using the test is quick and returns almost instantly.
I want the first scenario described to be as quick as the second one.
Please let me know how best to resolve this, and if there is a better way to test the connectivity to a DB quickly please advise.
There really is no easy or quick way to resolve this. The ConnectionTimeout value is getting ignored with the Entity Framework. The solution I used is creating a method that checks if a context is valid by passing in the location you which to validate and then it getting the count from a known very small table. If this throws an exception the context is not valid otherwise it is. Here is some sample code showing this.
public bool IsContextValid(SomeDbLocation location)
{
bool isValid = false;
try
{
context = GetContext(location);
context.SomeSmallTable.Count();
isValid = true;
}
catch
{
isValid = false;
}
return isValid;
}
You may need to use context.Database.Connection.Open()
I am trying to register to a "Device added/ Device removed" event using WMI. When I say device - I mean something in the lines of a Disk-On-Key or any other device that has files on it which I can access...
I am registering to the event, and the event is raised, but the EventType propery is different from the one I am expecting to see.
The documentation (MSDN) states : 1- config change, 2- Device added, 3-Device removed 4- Docking. For some reason I always get a value of 1.
Any ideas ?
Here's sample code :
public class WMIReceiveEvent
{
public WMIReceiveEvent()
{
try
{
WqlEventQuery query = new WqlEventQuery(
"SELECT * FROM Win32_DeviceChangeEvent");
ManagementEventWatcher watcher = new ManagementEventWatcher(query);
Console.WriteLine("Waiting for an event...");
watcher.EventArrived +=
new EventArrivedEventHandler(
HandleEvent);
// Start listening for events
watcher.Start();
// Do something while waiting for events
System.Threading.Thread.Sleep(10000);
// Stop listening for events
watcher.Stop();
return;
}
catch(ManagementException err)
{
MessageBox.Show("An error occurred while trying to receive an event: " + err.Message);
}
}
private void HandleEvent(object sender,
EventArrivedEventArgs e)
{
Console.WriteLine(e.NewEvent.GetPropertyValue["EventType"]);
}
public static void Main()
{
WMIReceiveEvent receiveEvent = new WMIReceiveEvent();
return;
}
}
Well, I couldn't find the code. Tried on my old RAC account, nothing. Nothing in my old backups. Go figure. But I tried to work out how I did it, and I think this is the correct sequence (I based a lot of it on this article):
Get all drive letters and cache
them.
Wait for the WM_DEVICECHANGE
message, and start a timer with a
timeout of 1 second (this is done to
avoid a lot of spurious
WM_DEVICECHANGE messages that start
as start as soon as you insert the
USB key/other device and only end
when the drive is "settled").
Compare the drive letters with the
old cache and detect the new ones.
Get device information for those.
I know there are other methods, but that proved to be the only one that would work consistently in different versions of windows, and we needed that as my client used the ActiveX control on a webpage that uploaded images from any kind of device you inserted (I think they produced some kind of printing kiosk).
Oh! Yup, I've been through that, but using the raw Windows API calls some time ago, while developing an ActiveX control that detected the insertion of any kind of media. I'll try to unearth the code from my backups and see if I can tell you how I solved it. I'll subscribe to the RSS just in case somebody gets there first.
Well,
u can try win32_logical disk class and bind it to the __Instancecreationevent.
You can easily get the required info
I tried this on my system and I eventually get the right code. It just takes a while. I get a dozen or so events, and one of them is the device connect code.