Thursday, April 14, 2016

.Net: Getting an Existing Code-First Solution Running Against a Rebuilt Database

Most of my posts are linux related, since I run that at home and encounter problems to solve due to being a relative newcomer. Occasionally, though, I run into something at work worth posting about (I'm a .Net developer).

I ran into a problem pointing an existing Code-First solution to a Dev database instance that I had restored from backup. I spent quite a bit of time working through all of the various issues that this situation caused, so hopefully the solutions I found will help someone else down the road. You may find that you only have some of these issues, depending on how the solution you're dealing with is configured.

The main problem I had was, after I had switched the connection strings in the project over to my new DB instance, the site threw an error: "Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration. You can use the Add-Migration command to write the pending model changes to a code-based migration." In order to fix this, though, it turned out I needed to do a few things first - the dreaded Yak Shaving. Down the rabbit-hole we go!

So the goal is to get your database synchronized. In my case, I had a very recent production backup, so I knew there were very few, if any, actual differences between the database and the existing model in the project. To do this, you'll need to be able to run some entity framework commands in the package manger console. You might be getting an error trying to run "update-database -script" as I was; or you might have already discovered that isn't the first command you need to run and have been getting an error running the "add-migration" or "enable-migration" commands. The error that I received was: "The term 'Update-Database' is not recognized as the name of a cmdlet, function, script file, or operable program." The root cause turned out to be an error in packages.config; one of the files was listed twice. Here are the steps I used to fix it:

  1. Open packages.config. Simply use CTRL + , and type packages into the prompt that comes up. It'll find the file immediately. (This is equivalent to CTRL + SHIFT + r in eclipse).
  2. Comment out any duplicate entries (CTRL + k + c) and save your changes.
  3. Open the package manager console. If you don't see it as one of the minimized tabs in VS, use View->Other Windows->Package Manager Console.
  4. Type enable-migrations and hit enter.
  5. If you get a message saying migrations are enabled or migrations are already enabled, you're good. If you still get the "not recognized as cmdlet" message, keep going.
    1. Check the version of entity framework listed in packages.config. If it is not listed, check the version of the .dll in your references folder.
    2. In the package manager console, type "install-package EntityFramework -version 5.0.0.0" (or whatever version you need) and hit enter.
    3. You should get a message that either the package has been installed successfully or that it was already installed.
    4. Restart Visual Studio.
Now when I ran the commands, I got a different error. I always chalk that up as a win. I find that as long as I keep getting new errors, I'm probably getting closer to the final solution. In this case, it was "Could not load file or assembly EntityFramework .. or one of its dependencies". It took some real digging to find the solution to this one. In this case, it is to copy the contents of the EntityFramework NuGet package into an alternate location where Visual Studio 2015 expects it.
  1. In your project, open your references node and right click on EntityFramework. Select Properties.
  2. Copy the Path item, excluding the EntityFramework.dll portion.
  3. Open windows explorer and paste the path into the location bar. No location bar? Paste the path into IE instead, it'll bring up windows explorer to the correct location.
  4. Use the location bar or back directory arrow to go all the way back to the packages folder.
  5. Right click and copy the EntityFramework folder.
  6. Open a windows explorer window to C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\EFTools
  7. Create a new folder in this location called NuGet Packages.
  8. Inside the NuGet Packages folder you just created, paste the EntityFramework folder.

Once I'd done that, the entity framework commands were available to me in package manager, and they actually worked! Now I needed to actually do the work of synchronizing the database. This turns out to be a relatively straightforward process:
  1. Open the package manager console if it isn't already open. See step 3 above if you don't know where to find it.
  2. If you're not sure if migrations are enabled, run the command: "enable-migrations".
  3. Assuming that was successful or the project was already set that way, you'll want to add a migration. You'll need to give it a name, say ProjectName001. Run the command: "add-migration ProjectName001".
  4. This should have created a .cs file containing what your project thinks the differences are.
  5. Now, rather than letting the machine try to make the migration automatically, you can create a SQL script that you can adjust by hand. If you have experience with SQL, I recommend this route.
  6. Run the command: "update-database -script". This will generate a SQL script that will then be displayed in Visual Studio.
  7. Save the SQL script, and look through it and see if it's doing anything dumb. In my case, the script wanted to add several columns that already existed, as well as drop a number of useful indexes and foreign keys. I commented this code out, which ended up leaving just one line, the one that starts with "INSERT INTO [__MigrationHistory]"
  8. Run your adjusted SQL script against your database instance. I used SQL server management studio, because old habits are hard to break, but you can run SQL inside Visual Studio if you want.
    1. Click the connect icon (server icon thing) at the top of the window and enter the name of your database instance. Click the connect button on the dialog.
    2. Execute your script (CTRL + SHIFT + E)
The key thing is that now I had a new record in the __MigrationHistory table that will allow the Code First solution to run! Since my database sufficiently matched, at this point my solution ran just fine.

Hopefully this helps someone else, I know this cost me significant time to research and fix.

Useful links that helped me construct this guide:
http://stackoverflow.com/questions/9674983/the-term-update-database-is-not-recognized-as-the-name-of-a-cmdlet
https://github.com/NuGet/NuGetGallery/issues/2592
http://stackoverflow.com/questions/20968520/entity-framework-code-first-migration-fails-with-update-database-forces-unnecc
https://msdn.microsoft.com/en-us/data/dn579398.aspx#option1

Sunday, August 30, 2015

Upgrading the firmware on TrendNet TEW-731BR

If you’re like me, and you tried to upgrade your router firmware, but found that you get a checksum error, you may want to try an alternate version of the firmware. After all, any newer firmware is probably better than what you have, if you have the factory default.
 
If you happen to have a TrendNet TEW-731BR, I have some specifics on how do this. The newest version (1.03b01) appears to have a flaw that prevents the router from running it. It did not matter how many times I tried to download and extract it, it failed every time. If you have this same issue, you'll need to grab the version prior to that (1.02b05), released June 26, 2014. I found it at http://download.trendnet.com/TEW-731BR/firmware/ which is the repository for all the TrendNet firmware downloads.

I was able to upgrade my TEW-731BR (1.0R) router without any issues using the 1.02b05 firmware.

Note that if you have a TEW-731BR and the router itself it does not have GREENnet written on it, you may have the TEW-731BR (2.0R). This is a different router and has a different firmware, which you can get from the TrendNet site here: http://www.trendnet.com/support/supportdetail.asp?prod=235_TEW-731BR

Updating the firmware is quite painless, simply open up the firmware admin, go to tools->firmware. Click the browse button and select the .bin file of the firmware you downloaded and extracted, and then click Update. After the processing countdown, the new firmware will be loaded, with all of your previous settings preserved.

Monday, June 29, 2015

LMT #4: A Simple Desktop Background Slideshow

Linux Mint Tips #4: A Simple Desktop Background Slideshow

Linux Mint Tips series is a list of tricks I've picked up after having switched away from Windows for good in 2013, after dabbling for years. I'll do my best to go back and edit posts that contain any erroneous information, but keep in mind that I'm a relative newcomer to the Linux scene. I wrote this tutorial running the MATE desktop environment in Mint 17.1.

The desktop background is often one of the first things I customize after installing a fresh OS, and that's no exception in Mint. I have a couple of preferences: one, I like the image to change every so often, and two, I prefer landscapes. In other operating systems, setting up this sort of thing is a built-in, point-and-click affair. In Mint, it is possible, but there's a little more legwork (but not too much).

For the example provided here, download and save the following images to your Pictures folder. Please note that the tutorial uses the 1920x1080 resolution size. If you need to choose an alternate size, you'll have to tweak the image names in the .xml file. You'll also need to copy/paste them over into Pictures from the Downloads folder if you're using the default browser settings.
https://interfacelift.com/wallpaper/details/1489/tree_and_the_mountain.html
https://interfacelift.com/wallpaper/details/2031/ageeba.html
https://interfacelift.com/wallpaper/details/2053/autumn_mill.html
https://interfacelift.com/wallpaper/details/1940/moraine_lake.html
https://interfacelift.com/wallpaper/details/1494/lonesome_house.html

Once you have those, you'll need to grab the xml file that drives the slideshow.
https://drive.google.com/file/d/0B87z1DYb0jIoZjVqSkdNeHdHdmM/view?usp=sharing

I recommend putting this in the Pictures folder as well. You'll need to edit the file and change /home/harborpirate to substitute your own home folder name instead of harborpirate.

Right click on the desktop and click Change Desktop Background. Change the dropdown setting from Images to All Files. Choose Interface.xml.

What this xml file contains is the instructions for the locations of the files, what order they should be swapped, what transition to use, how long the transition lasts, and how much time between transitions.

I've kept this example relatively simple, but with enough detail to hopefully be useful. Enjoy.

Wednesday, April 22, 2015

Light Color Icon for Gridster Resize Handle

If your site has a dark theme and it is difficult to see the dark resize icon that gridster uses, I've got a fix for you.

In the jquery.gridster.css, you'll see that .gs-resize-handle-both includes a base64 encoded image for background-image. You may think that it'll be a pain to change this, since you'll need to decode, save as a file, edit, save again, open the file in binary mode, copy the text, and then re-encode, but its actually a little simpler than that.

First, grab the base64 encoded string from the css. The master branch file is here: https://github.com/ducksboard/gridster.js/blob/master/src/jquery.gridster.css, and the following is the actual base64 encoded string of the resize handle image if you want to follow along but can't be bothered to open that file:
PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg08IS0tIEdlbmVyYXRvcjogQWRvYmUgRmlyZXdvcmtzIENTNiwgRXhwb3J0IFNWRyBFeHRlbnNpb24gYnkgQWFyb24gQmVhbGwgKGh0dHA6Ly9maXJld29ya3MuYWJlYWxsLmNvbSkgLiBWZXJzaW9uOiAwLjYuMSAgLS0+DTwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DTxzdmcgaWQ9IlVudGl0bGVkLVBhZ2UlMjAxIiB2aWV3Qm94PSIwIDAgNiA2IiBzdHlsZT0iYmFja2dyb3VuZC1jb2xvcjojZmZmZmZmMDAiIHZlcnNpb249IjEuMSINCXhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbDpzcGFjZT0icHJlc2VydmUiDQl4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjZweCIgaGVpZ2h0PSI2cHgiDT4NCTxnIG9wYWNpdHk9IjAuMzAyIj4NCQk8cGF0aCBkPSJNIDYgNiBMIDAgNiBMIDAgNC4yIEwgNCA0LjIgTCA0LjIgNC4yIEwgNC4yIDAgTCA2IDAgTCA2IDYgTCA2IDYgWiIgZmlsbD0iIzAwMDAwMCIvPg0JPC9nPg08L3N2Zz4=

Next you'll need a tool to decode this string. There are numerous ones online, including the one I ended up using:
http://www.motobit.com/util/base64-decoder-encoder.asp

Paste the string into the large textbox and choose the decode radio button item. You do not need to change any other settings. Click the "convert the source data" button. You'll now end up with a second textbox containing some xml that defines the original svg image. Here's that xml:

<?xml version="1.0" standalone="no"?>
<!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.1 -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="Untitled-Page%201" viewBox="0 0 6 6" style="background-color:#ffffff00" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
x="0px" y="0px" width="6px" height="6px"
>
<g opacity="0.302">
<path d="M 6 6 L 0 6 L 0 4.2 L 4 4.2 L 4.2 4.2 L 4.2 0 L 6 0 L 6 6 L 6 6 Z" fill="#000000"/>
</g>
</svg>

This seems like the point where you'll need to deal with all the complexity of saving this as a file and using an svg editor to make modifications to it, but as it turns out, the change that needs to be made is so simple that you can just edit this text by hand. The key pieces are the opacity setting and the fill color. What you'll want on a dark themed site is to up the opacity slightly, and choose a light color for the fill color. I set the opacity value to 0.85 and the fill to #dddddd, but you can tweak these however you like. Just remember that opacity is a decimal between 0.00 and 1.00 and that fill is a hex value between #000000 (black) and #ffffff (white). Be careful about setting the value to pure white (#ffffff). Since we do not see the background color at all, I'm pretty sure that the background-color is being used as the transparency color; thus using pure white for a fill color may result in not seeing anything at all. If you need to do that, you may need to experiment a little with the effects of changing the background-color value.

At this point you'll have a new xml, like this one:

<?xml version="1.0" standalone="no"?>
<!-- Generator: Adobe Fireworks CS6, Export SVG Extension by Aaron Beall (http://fireworks.abeall.com) . Version: 0.6.1 -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="Untitled-Page%201" viewBox="0 0 6 6" style="background-color:#ffffff00" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
x="0px" y="0px" width="6px" height="6px"
>
<g opacity="0.85">
<path d="M 6 6 L 0 6 L 0 4.2 L 4 4.2 L 4.2 4.2 L 4.2 0 L 6 0 L 6 6 L 6 6 Z" fill="#dddddd"/>
</g>
</svg>

To translate this back into the encoded format to replace the value in the css, copy and paste this text back into the base64 tool, making sure to paste it into the bottom textarea (the input one). Change the option to encode. If you used the same values I did, you'll get the following back in the top textbox as the result after you click the "convert the source data" button:

PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIEZpcmV3b3JrcyBDUzYsIEV4cG9ydCBTVkcgRXh0ZW5zaW9uIGJ5IEFhcm9uIEJlYWxsIChodHRwOi8vZmlyZXdvcmtzLmFiZWFsbC5jb20pIC4gVmVyc2lvbjogMC42LjEgLS0+DQo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPg0KPHN2ZyBpZD0iVW50aXRsZWQtUGFnZSUyMDEiIHZpZXdCb3g9IjAgMCA2IDYiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNmZmZmZmYwMCIgdmVyc2lvbj0iMS4xIg0KeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSINCng9IjBweCIgeT0iMHB4IiB3aWR0aD0iNnB4IiBoZWlnaHQ9IjZweCINCj4NCjxnIG9wYWNpdHk9IjAuMzAyIj4NCjxwYXRoIGQ9Ik0gNiA2IEwgMCA2IEwgMCA0LjIgTCA0IDQuMiBMIDQuMiA0LjIgTCA0LjIgMCBMIDYgMCBMIDYgNiBMIDYgNiBaIiBmaWxsPSIjMDAwMDAwIi8+DQo8L2c+DQo8L3N2Zz4=

You can now replace the base64 encoded image value in the jquery.gridster.css file with this one, and you'll end up with a lighter colored resize handle in gridster.

You could certainly get a lot more sophisticated and choose different images depending on the color of the consuming component, but this was as far as I needed to go since the site I was working with has a consistent theme that puts a dark color at the bottom of the widgets.

Saturday, December 20, 2014

LMT #5: Simple TV Tuning (with Win TV PVR)

Linux Mint Tips #5: Simple TV Tuning (with Win TV PVR 500)

Linux Mint Tips series is a list of tricks I've picked up after having switched away from Windows for good in 2013, after dabbling for years. I'll do my best to go back and edit posts that contain any erroneous information, but keep in mind that I'm a relative newcomer to the Linux scene. I wrote this tutorial running the MATE desktop environment in Mint 17.1.

I have an older TV capture card in my PC. It still works just fine, but I ran into some problems when I started trying to use it to view TV in Linux Mint 17.1. Namely that the TV watching packages (Myth TV, Me TV, pretty much every linux TV viewer) only work with DVB (digital video broadcast) devices, of which the older PVR series are not. After some time, I gave up searching for a nice looking piece of software and started looking for anything that worked. That's when I found a few useful guides and tips, which I'll distill for you here:

Part 1, Tuning:

Open Package Manager and install the ivtv-utils package (you'll have to enter the password of your elevated account to start package manager. After you've searched and found ivtv-utils, click on the checkbox next to it. Select mark for installation. It'll ask if you want to install dependencies. Choose Mark so they'll be installed also.)
Open VLC player (comes pre-installed on Mint).
Click on the Media menu, then select Open Capture Device.
Click PVR in the Capture Mode dropdown then click the Play button.
If you do not have a PVR option, you will need to close VLC and then open Terminal. Type, or better yet, copy and paste in this command: vlc 'v4l2c://' >/dev/null 2>&1 & and hit enter. This will start VLC in the correct mode for PVR devices.
Open Terminal, if it isn't already open, and enter ivtv-tune -c33 (33 is channel number, so use whatever channel you like)
You should now have a valid signal and you should be able to watch TV. You can use the ivtv-tune terminal command to change the channel at any time.

Part 2, Adjusting the view:

Turn on deinterlacing to reduce the "jaggy" effect. In VLC, click on the Video menu, select Deinterlace, then select On.
For channels that show widescreen inside the 4:3 frame, which is most of them these days, there is a useful zoom function. Click on the Video menu, select Crop, select 16:9.
To show in true fullscreen mode, use the following two options in succession: Click on the View menu, and select Fullscreen Interface. Then click on the View menu again, and select Minimal Interface. You can get out of this mode using the Esc key or by right clicking on the video itself to get the menu options to come up so you can toggle these modes back off.
To enable recording, click on the View menu and select Advanced Controls. This will enable the record icon in the bottom control bar. Videos are recorded to your home/Videos folder.

Thanks very much to the following guides and answers that helped me put together this tutorial:

Monday, October 13, 2014

LMT #3: Setting Up A Low-Privileged "Kids Account"

Linux Mint Tips #3: Setting Up A Low-Privileged "Kids Account"

Linux Mint Tips series is a list of tricks I've picked up after having switched away from Windows for good in 2013, after dabbling for years. I'll do my best to go back and edit posts that contain any erroneous information, but keep in mind that I'm a relative newcomer to the Linux scene. I wrote this tutorial running the MATE desktop environment in Mint 16.

One thing I ran into after setting up my Linux machine was that I needed a secondary account that my son could log into. At this point he plays web games on well known sites, under frequent supervision. One thing that's important to him is a sense of independence, so having a foolproof method to start the computer and get logged in was key.

You could potentially use the same idea if you wanted to have a guest account, or if you were setting up a machine for a friend or relative who was less computer savvy, or perhaps just your own convenience.

This left me with two goals:
  • Create a low-privileged account 
  • Make sure that account can log in automatically

Setting Up A Secondary Account
Menu->Control Center->Users and Groups.
Click the Add button.
Type a name and click OK.
Type in a password twice and click OK.

Set That Account To Log In Automatically
Menu->Control Center->Login Window
Click the Auto Login tab.
There are two options: One will log in a user automatically immediately, the other will log them in after a set amount of time. I like the timed option because it gives me the chance to log into my account instead if I'm using the machine. Here's how you do the rest:
Check the box, pick the secondary account out of the list, and if you’re using the timed option, set the number of seconds to wait before that account is auto-logged in.
The lowest possible time for this setting is 10 seconds.
Click Close.

That's it. The secondary account will now automatically be logged into when the machine starts. Low-privilege is the default setting, so there was no need to mess with the default account settings when it was created. Note that the account still has a password; I would never recommend setting up an account that lacked a password, nor would I recommend setting up automatic login on a laptop that I carried around to work or school. Furthermore, I would not recommend turning on this option on any account with high-level privileges; even though Linux Mint is good about requiring your password to do anything potentially harmful, there's no need to ask for trouble when setting up a secondary account is so easy.

Thursday, July 17, 2014

Verizon's New Weird Trick To Prevent Tethering

You may recall that Verizon lost a court case that forced them to allow tethering and wi-fi hotspot apps for users who do not have unlimited data. Or did it?

Here's one of the articles that describes the ruling:
http://www.zdnet.com/let-my-wi-fi-go-fcc-rules-verizon-cant-charge-for-wi-fi-tethering-7000001916/

Verizon, for its part, hasn't given up trying to charge for this feature. They found a loophole.

Their current strategy: comply with the letter of the law, but not the spirit.

Their new trick is a multi-pronged plan:
1. Allow users to download third party wi-fi hotspot programs in order to comply with the ruling. The ruling only forced Verizon to assert that "it no longer objects to the availability of the tethering applications to C-Block network customers”. Which, by allowing users to download such programs, they technically comply with.
2. Release Android operating system updates that are specifically customized to prevent third party wi-fi apps from actually enabling a wi-fi hotspot on the phone. These apps can be installed and run by the users, but they don't do anything.
3. Continue to charge a monthly fee for enabling the wi-fi hotspot functionality that is integrated into the Android OS, offering users a single alternative: upgrade to a [more expensive] plan that includes the hotspot function.

The only recourse for the customer: root the phone and replace the operating system, which voids any warranty the customer may have had.

Verizon doesn't have much to lose. The settlement resulted in a fine that amounted to a mere slap on the wrist. $1.25M is almost certainly less than the amount that they make annually from users duped into paying the extra fee. Any future ruling represents an insignificant risk, well worth flaunting for the ability to continue to fleece customers out of another $20 a month for data that they already pay for.