Pages

Saturday, January 16, 2021

For those of you stalwart followers who like me here, I am splitting out the SQL Server posts to a new blog.


Find it here.

Posts that apply to both Visual Studio development AND SQL Server will probably be posted on both sites.


...


Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Friday, November 6, 2020

SQL Server: My AutoIncrement Column is Skipping Values (solved)

There is a long explanation about SQL server caching values for autoincrement columns, and losing them when the server is restarted, but the fix is this:


USE [database_name]
ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE = OFF
GO

This does incur a performance hit, so if you're inserting 20 billion records a day, be warned.  But for a normal web or app database, this will make it more likely that your autoincrement values will step up the way you had intended.

...


Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Tuesday, July 21, 2020

Unforgivable Sins

Last night we had a power outage, so I left my PC off all night.  When I rebooted, guess what happened?

Slack - a program I had very clearly configured to run-on-demand suddenly decided it needed to launch on startup.  I don't now and never have used Slack as a primary means of communication, and the thought that they would take ownership of my PC because they think they know what's good for me is - well it's unforgivable.

Uninstalled.

When you write code, I know it's easier to think your customers, pirates, and family members love your software so much that they want it front and center 100% of the time, but mostly, they don't.  In fact, my computer boots so slowly that I purposely turn off all those autoupdaters that run on startup.

Google Updater, Adobe Updater, Java Updater, Daz, Unity, Apple (for iTunes, another program I rarely use), Avast, Malware Bytes, Carbonite.  All of these updaters are disabled, because when I reboot, it takes my hard drive 15 minutes to fully boot.  The mouse and icons are there early, but if I try to launch anything it takes 300x as long and it's just not worth it.

Every time I have to disable these malware bots, I have to search startup, the task scheduler, and 4 other places to make sure they haven't found some new, hidden way to infiltrate my system.  It wouldn't be so bad if there was a task in the scheduler that would launch the updater, say at 3:46AM and check for a patch, then CLOSE THE UPDATER, but no, the updater must remain running for the rest of time.  Some software companies even have a second program that makes sure the first program is never stopped.

Programmers: These practices will get you into the Special Hell.  The one reserved for child molesters and people who talk in the theater.

...


Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, July 16, 2020

The solution you are opening is bound to source control on the following Azure DevOps Server:

Unlike Git or Subversion, when you move your projects to a new path, say to organize your hard drive, you'll see this warning when you open your project.

---------------------------
Microsoft Visual Studio
---------------------------
Team Foundation Server Version Control

The solution you are opening is bound to source control on the following Azure DevOps Server: http://...collection. Would you like to contact this server to try to enable source control integration?
---------------------------
Yes   No   Help  
---------------------------

Pressing Yes is useless.  Right clicking your project gives you the option of adding it, not reconnecting it.

Here's the procedure to fix this issue.

  1. Close your solution.
  2. Close the What would you like to do? window.
  3. File -> Source Control -> Advanced -> Workspaces.
  4. You may see many workspaces in the list, highlight the one that matters.
  5. Edit.
  6. You will see a list of Source Control Folders connected to Local folders. 
  7. Click on the Local Folder (you'll see the OLD location) and fix it to the new location.
  8. Repeat for all the solutions you want to fix.
  9. OK, Close
  10. Bob's your uncle.  You can edit the project without the scary warning with the "fix" that doesn't work.
  11. (optional, but recommended) Ditch Azure Devops Because it's lame, and use Subversion or Git.

Friday, July 3, 2020

ASP.NET MVC - Simple 5 Step JQuery Filter.

Using this 5 step process you can add a client-side JQuery filter to your MVC Index pages.   

  1. Set up your layout page so that the JQuery pages load BEFORE the page loads.
  2. Add a filter bar.
  3. Add a <thead> and <tbody> section to your table (so we don't inadvertently filter the header row).
  4. Add data- tags to your <tr>s.
  5. Add jQuery to respond to the keyup event in your filters.

Layout page

In your Views/Shared/_Layout page, there is a block of code at the end that looks like this:

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)

Move these to the line just after

    @Scripts.Render("~/bundles/modernizr")

...at around line 8.  The JQuery library needs to be loaded before the @RenderBody line.  This step only needs to happen once for your whole app, unless you're using multiple layout pages.

Filter Bar

Next we'll need a filter bar to the index page.

Let's say we want to filter by three fields:

I put this just before the <table>.

<div class="icon-bar">
    <span style="font-weight:bold;">Filters</span>&nbsp;&nbsp;
    State: <input name="State" id="state" type="text" style="width:35px;" maxlength="2" class="filter" />&nbsp;&nbsp;
    County: <input name="County" id="county" type="text" style="width:90px;" class="filter" />&nbsp;&nbsp;
    Town: <input name="Town" id="town" type="text" style="width:90px;" class="filter" />&nbsp;&nbsp;
    <span id="recordCount" style="font-weight:bold;">@Model.Count().ToString() records.</span>
</div>

class="icon-bar": use this class to style the bar how you like it: I used this in my style sheet, but you do as you like:

div.icon-bar{
    background:linear-gradient(#44f, #88F, #44F, #008, #000);
    padding:5px;
    margin-bottom:12px;
    border:1px solid black;
    border-radius:15px;
    color:white;
}

This makes the text in the input boxes white on white, so I added this:

input.filter{
    background-color:white;
    color:black;
}

thead and tbody

The first row in your table is the headers and we DON'T want to ever filter that row out.  So add a <thead> tag around the first <tr>

Now add a <tbody id="fbody"> around your data loop.

I use the id tag to find the tbody and access its rows in the jQuery.

Data- tags

Rather than use some wizardry to find what's in the <td> cells, I add custom tags to the <tr>s to help me hide/show them as a group.

@foreach (var item in Model){<tr data-state="@item.state" data-county="@item.county" data-town="@item.town">    

This adds tags for all the fields I want to filter for.

jQuery

This is easy enough.  Add a keyup function to all 3 filter fields.

<script type="text/javascript">
    $(".filter").keyup(function () { //this matches the class=filter on all 3 input boxes.
        //hide all trs in the tbody
        var rows = $("#fbody").find("tr").hide(); //this hides every row in the table body
        var workingList = rows;  //makes a list of all the table rows to work on
        //grab the text from the search box
        var state = $("#state").val().toLowerCase();
        var county = $("#county").val().toLowerCase();
        var town = $("#town").val().toLowerCase();

        //now show the ones where all values match

        if (state.length > 0) { //if there is any text in the first filter...
            //filter just returns a filtered list
            workingList = workingList.filter(function () {  //spawns a tiny inline function to test each row
                //return true if data-state starts with var state
                if ($(this).data("state").toLowerCase().indexOf(state) == 0) {
                    return true;
                }
                else {
                    return false;
                }
            })
        }

        if (county.length > 0) {
            workingList = workingList.filter(function () {
                //return true if data-state starts with var state
                if ($(this).data("county").toLowerCase().indexOf(county) == 0) {
                    return true;
                }
                else {
                    return false;
                }
            })
        }

        if (town.length > 0) {
            workingList = workingList.filter(function () {
                //return true if data-state starts with var state
                if ($(this).data("town").toLowerCase().indexOf(town) == 0) {
                    return true;
                }
                else {
                    return false;
                }
            })
        }
        $(workingList).show();  //show the rows remaining in the working list.
        $("#recordCount").text(workingList.length+" records.") //update the record count in the filter bar.
    });
</script>


That's it! You can see how I
  1. hide all the rows in the <tbody>
  2. grab the strings from the filter boxes.
  3. copy the list of all rows to workingList.
  4. Loop through the filters...
    1. check to see if there is any text in the filter strings.  (if not, skip that filter.)
    2. enact a function on each <tr> that looks for the data- values to match the string entered by the user.
    3. this filters out all the <tr>s that do not match.
    4. the 3 filters all work together successively eliminating more rows from workingList until we are done.
  5. we issue a show() to all the rows that are left in the list.
  6. we update the count in the filter bar.

Also, you C# programmers like me: Don't freak out that there are returns in the middle of the function.  Those returns are in the middle of a small inline function, and return to the main function, not from it.

Matching

I chose a "startsWith" match, that's why my functions have a .indexof(state)==0.  Here's some different ways to match.

exact match

if ($(this).data("town").toLowerCase() == town) {

contains match

if ($(this).data("town").toLowerCase().indexOf(town) >= 0) {      This should be a good start to filtering for any ASP.NET MVC index page using jQuery.                

Thursday, April 25, 2019

Automatically execute a SQL Command from an icon

You'll need SQL Server command line tools to run this.

Assuming:

  • you have a .sql file you want to run, 
  • you have a username/password and all that.
Create a batch file.
  1. In file manager, right-click somewhere in the folder you want to put it in (like Documents\batch) and New->Text file.
  2. Edit the name that comes up and call it [something].bat
  3. Windows may warn you about renaming file extensions.  Click OK.
  4. Right click the new file in file manager and Edit.  It should open in notepad.
  5. Add this text, using your own server, username and password.
sqlcmd -S ".\SQLEXPRESS" -U myUserName -P myPassword -i %1 -d DBName >result.txt
start Notepad.exe result.txt
Save the file.
See that %1 in there?  That means that the filename of  any .sql file you drop onto this bat file's icon will get inserted and the query will run, dropping the results into a text file (>result.txt)  
The bat file then opens notepad and shows the user the results.




...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Tuesday, December 18, 2018

Could not find stored procedure 'dbo.aspnet_CheckSchemaVersion'.

In my MVC app, I followed the OLD ASP.net roleManager and MembershipManager setup.

DO NOT DO THIS WITH MVC!

DO NOT RUN ASPNET_REGSQL!

Identity does NOT work that way anymore.

What I had to do was remove the line in my web.config that said:

    <roleManager enabled="true" cacheRolesInCookie="false"  />
Once I got rid of that, the error blessedly poofed into a memory.


...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Friday, December 7, 2018

Updating Object Relational Model Easily in MVC

So I got my mind around the models, if I change a field, I know how to modify the object properties to match.  Ditto the relationships - add a hashset here and there to reference linked items.
But I read the ORM (the main model page) and that thing just mystifies me.
Like this:

So a PrefCategory has many Prefs. got it.
But it has a required PrefCategory???  It requires itself? 

Anyhow, Applying the American credo just get it done, I came up with this:
To complete this tutorial you will need WinMerge.
First open up your relational mode in Models.  Copy all the text.

Open WinMerge, hit the 2 pages icon to create a new comparison,  and paste the code into the left pane.
Now in Visual Studio, create a new MVC project.  in Solution Explorer, right click Models - Add - Ado.Net Entity Model.
Choose your development database, and tick all the same tables and views you are using in your main app.
It will create all the table models.
Now open the same relational model, copy all and paste it into the right pane of WinMerge.  Hit Refresh.
Now you'll see everywhere that your code differs from what you'd see if you imported the model fresh.
In my case, I could easily see where I had an old .WithOptional that had now become a .WithRequired.  I modified my project relational model and suddenly I was no longer getting the

Multiplicity conflicts with the referential constraint in Role 'blah blah thing that doesn't exist by that name anywhere in the project' in relationship 'blah blah'. Because all of the properties in the Dependent Role are non-nullable, multiplicity of the Principal Role must be '1'.
errors.


Wednesday, November 28, 2018

SQL Server: How to Concatenate Parent Nodes in Irregular Category Trees

Consider this table:

id ParentCategory Name
1 NULL Household
2 1 Furniture
3 1 Appliances
4 2 Chair
5 2 Couch
6 2 Bed
7 3 Refridgerator
8 3 Counter
10 3 Bathroom


We want each node to display all it's parents back to its root. This SQL helps.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:        bryanv
-- Create date: 11/28/2018
-- Description:    gets the whole list from here down
-- =============================================
CREATE FUNCTION dbo.CategoryFullName
(
    @CategoryID int
   
)
RETURNS nvarchar(200)
AS
BEGIN
    -- Declare the return variable here
    DECLARE @ans nvarchar(200)
    declare @parent int

    -- Add the T-SQL statements to compute the return value here
    select @ans=name, @parent=ParentCategory from Categories where id=@CategoryID

    if @parent is not null
    BEGIN
        set @ans=dbo.CategoryFullName(@parent)+' - '+@ans
    END


    -- Return the result of the function
    RETURN @ans

END
GO


This will look up the current category text, and prepend all parents recursively until it gets to the root.
 You can then use this in a computed column to autogenerate the entire category tree.

Now you can automatically get the full tree with a simple select...



...


Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Tuesday, November 20, 2018

SQL Server: Return All Dates in a Range

This function will return a list of all dates between a start date and an end date.


SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:        bryan valencia
-- Create date: 11/20/2018
-- Description:    returns the dates between start and end (inclusive).
-- =============================================
CREATE FUNCTION DaysBetween(@startdate DATE, @enddate DATE)
RETURNS @calendar TABLE
(
    calendarday DATE PRIMARY KEY
)
AS
BEGIN
        -- Fill the table variable with the rows for your result set

    WITH calendar AS
    (
      SELECT CAST(@startdate AS DATETIME) DateValue
      UNION ALL
      SELECT  DateValue + 1
      FROM    calendar  
      WHERE   DateValue + 1 <= @enddate
    )

    insert into @calendar(calendarday)
    (
    SELECT  cast(DateValue as Date) calendarday
    FROM    calendar
    )
    OPTION (MAXRECURSION 0)
   

    RETURN
END
GO


To call it: SELECT * FROM [dbo].[DaysBetween] ('01 jan 2018', '01 feb 2018')



...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Wednesday, September 19, 2018

css Tab Bar Demo

You created a great tabbed interface or vertical menu but you hate it that the links in the menu only respond to clicks on the actual text.

This css style info will show you how to make the whole tab clickable by making the link fill the entire box.

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="Bryan Valencia">
  <meta name="Keywords" content="Tab, bar, demo, css, html5">
  <meta name="Description" content="A quick tab bar demo showing how to make an entire div clickable instead of just the text.">
  <title>Tab Bar Demo by Bryan Valencia</title>
<style>
.tab{
width:200px;
height: 20px;
margin: 0px;
padding:10px;
text-align: center;
vertical-align: middle;
display: inline-block;
color: black;
background-color: white;
color: black;
background-color: aliceblue;
border: 1px solid silver;
border-top-right-radius: 10px;
border-top-left-radius: 10px;
border-bottom-right-radius: 0px;
border-bottom-left-radius: 0px; }
.tab:hover{
color: yellow;
background-color: green;
}
a.clickable-tab{
color: black;
display:inline-block;
width:100%; height: 100%;
vertical-align:bottom;
font-family:Arial, helvetica;
text-decoration:none;
}
.tab-bar{
display: block;
border-bottom: 1px solid silver;
padding:0px;
margin:0px;
background-color: gray;
}
</style>
 </head>
 <body>
<div class="tab-bar">
<h1>Tab Bar Demo</h1>
<div class="tab">
<a href="#" class="clickable-tab">Home</a>
</div><div class="tab">  <!-- the divs are wrapped funny here to prevent space between the tabs. -->
<a href="#" class="clickable-tab">About</a>
</div><div class="tab">
<a href="#" class="clickable-tab">Contact Us</a>
</div>
</div>
 </body>
</html>





...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, April 26, 2018

Changelog.txt. Playing with their heads.

Today I was checking my server logs for the root IP address.  This is people who are scouring the internet by IP address looking for whatever they can find.

One file I noted a lot of 404's for was CHANGELOG.TXT.  Apparently this is a DRUPAL file that might contain the current versions of some of your server's software.

Because I like to mess with these net scanners, I created this batch file.  It creates a sparse 1 gig file full of zeroes.

What is a sparse file?  It's a compressed file that seems to be big, but only takes around 4096 bytes on the drive.

@echo off REM MakeChangeLog.bat
REM You Should place this batch file in the folder you want to create the file in.
REM You must run this batch as an administrator!
REM Note that you must have the disk space to initially create the file before it gets compressed.

fsutil file createnew changelog.txt 1000000000
fsutil sparse setflag changelog.txt
compact /c changelog.txt

pause
This resulted in a 4096 byte file on my Windows Server 2012, and a 0 byte file on my Win 10 machine.  This file STILL downloads as a 1 gig file.  You can check the file size by right-clicking CHANGELOG.TXT and selecting Properties.

One caution: Do not do this with real files like robots.txt.  This file is legitimately used by search engines to figure out what you want scanned.  You're going to burn in a very special level of Hell.  A level they reserve for child molesters, and people who talk in the theater.

Enjoy!


Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Wednesday, March 21, 2018

MVC: A public action method ... was not found on controller

You have a page with something embedded, a partial view, a generated image, or something.  And it's odd, but the first time you load the page, everything works, but every time you reload (like someone clicks a button on the page), MVC claims it can't find the action.

InnerException:
ErrorCode=-2147467259
HResult=-2147467259
Message=A public action method ... was not found on controller '...Controller'.
Source=System.Web.Mvc
WebEventCode=0

You check and the action is right there!.  In my case it looked like this.

//Get: ProductPartial Blocks
[HttpGet]
[AllowAnonymous]
public ActionResult ProductBlockPartial(int? ID)
{
if (ID.HasValue)
{
Product model = db.Products.Find(ID);
return PartialView(model);
}
else
{ return null; }
}

The answer, my friend, is that pesky [HttpGet].  That tells the action to only respond to get requests, and when you pushed the button to post data back to the page, it became a post.  And the post flows down from the main page to the partial view as well.
Just remove the [HttpGet] from the action and you're good as gold!

...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Support

Back in the annals of history, companies wanted people to buy their software.  Most bought software came with a thing we used to call support.

Soon, places like Apple and Microsoft were getting 650 billion calls a day from every grandma that couldn't figure out how to get the cup holder to pop out.

What we really need, thought the beleaguered support operators; is a way to prevent people from accessing support. 

Support Barriers
I used to email support with a simple problem, or file a help ticket, and In the 90's I started seeing this...

I can't get the mouse to select the object in the window.

I started seeing responses like this:

Please tell us:

  • the model of your pc, 
  • the exact version of Windows, 
  • the serial number on your motherboard,
  • the embedded digital signature of your CPU
  • The exact amount of RAM, and wither it's DRAM or SRAM,
  • The exact error message you are seeing,
    • in Gaelic
  • Your exact DNA sequence,
  • and the serial number of your ISP's router.
In other words, that should get him off our backs for a while...


Expensive Support
Many things were tried.  I once had a Microsoft update eff up my web server and I waited 3 hours on hold, got a tech, and explained my problem.

His first question was, How will you be paying for this?

I won't,  I said.  You did this, not me.

Sorry, no support without payment.

OK, how much is it?

$400 to get through for 15 minutes, and there's no guarantee we will solve your problem.

But I paid over $400 for the server software to begin with!  

Sorry.  Credit card or pound sand.

I'm sure this way Microsoft could fire 80% of their foreign call center, and get back to the business of putting out flawed updates every 2 days.

Premium Support
Then came the thing where you'd pay $150 for some piece of software, and then $99 a year for premium support.  That's fine if you're using something big and mission critical, but with different support agreements on your word processing, email, databases, and on and on,  you end up paying a LOT of money every month for support.

SAAS
This is the latest in irony.  Software as a service.  It's partiucularly ironic because it contains the word service.  What SAAS means is that when you buy software, you're not buying anything.  In fact there are some packages (I'm looking at you Adobe Creative Cloud) that they want you to pay monthly for.

So all these guys who are making videos for YouTube now have to pay up monthly, while those of us who just wanted to add titles to a company presentation once, are OUT.

The truth is that you never OWNED software in the first place.  You held a limited license to use it.  If you OWNED Excel, you could sell it to someone else, or freely modify it.  It's not like a lawnmower, with which you can do what you like, it's more like paying to hear a song at a concert or a movie at a theater.  You don't OWN Star Wars because you saw it.

But I digress.

No Support
I just paid $50 for some software that made some claims on their web page, but due to a glaring BUG, it doesn't work on my machine.  I clicked support and got this:

If you have any issue with your purchase or related to the configuration of [the software], please post your request in the [user] forums, in the Troubleshooting section.
So, you fling out software, charge money, and then leave it to other users to figure out the problems by themselves?

Lawnmowers
It should be noted that anytime I have a question or problem about my lawnmower, I can still call the manufacturer.

Freeware, Shareware, Open Source
So I can fully understand why many people left the world of paid software and embraced free software.  There is usually a large user community, and you can even download it and modify it yourself (not that I would ever do that). 

The thing with open source is that there is still no support - but there is also no expectation of support.  Some small team of developers all over the world kind of run the project, and they all work for free in their mom's dank basement surrounded by Burger King and Dorito's bags.

These guys usually have Bugzilla going and they take the flurry if bugs from the clients, and choose some to rectify.  But the forums... that is a different animal.

Here's what software development looks like from a development teams point of view.


  1. You and a few friends decide that it would be cool to have an open source version of (x).
  2. Work for 3 years (for free) in every spare moment with the team to get the software where you want it.
  3. Miss your deadline and work another two years, promising that it'll be next month 24 times.
  4. Finally you get a working build (YAY)
  5. You release it to the webosphere.
  6. Here come the comments!
    1. Waited too long for crap software!
    2. It doesn't have all the features that the commercial $300 + $50 a month package has.
    3. When is it coming out for Mac?
    4. When is it coming out for Linux?
    5. It sicks. You suck. Drink bleach.
    6. I tried posting 50 messages on the forums, and no response from the team
    7. Why isn't there a Latvian version?
  7. So now you have 6,000 requests, of which there are maybe 20 real issues, and everyone thinks you can just quick-fix their thing.
    1. even though the source is open, they can download it and try to fix it at any time.
  8. Everyone gets mental when you don't release weekly bug patches.
  9. One or two people really praise it, but everyone else gripes about it.
  10. After about 2 years, no one wants to work on the project anymore, and there are no more updates.
  11. People continue to download it and fill the forums with requests, only to give up when no one answers.



...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Monday, March 12, 2018

How to Copy a MSSQL Server database to a New Webhost without RESTORE

This article explains how to copy a database from one server to another when Backup/Restore is not an option.

  • This will work as long as you have SQL Server Management Studio access to the source and destination databases.
  • This is very slow, and may take many hours to run on a big database.
  1. First, open the database server you want to copy in SSMS.
  2. Next, Right-click the database, Tasks -> Generate Scripts.
     
  3. In my case I want all the scripts to completely recreate my database, so here are the steps.
  4. Next
  5. Script entire database and all database objects
  6. Save to new query window (file is OK too).
  7. Click Advanced (by default it will write a script to create all objects, but not copy data).

    Make sure to select Schema and data.
  8. Review all the other settings to make sure you get the stuff you want on the destination database.  Click OK, then Next.
  9. Review and Next (or previous if you need to change something.)
  10. You'll get a checklist screen and then the script is done.  It should pop up in SSMS.
To restore the database...
  1. Log SSMS into the destination database.
  2. Back up what's there if there is any chance you'll need it.
  3. In your script, if you need to rename the database to satisfy the new hosting company, do a global replace in the SQL script.  Make sure the FileNames reflect the destination database name not the source database
  4. Copy the entire script to the clipboard.
  5. right click the destination database and do a New Query (if the database hasn't been created yet, you can click the server name).
  6. Paste the script into the new query editor.
  7. If the database already exists, you may need to delete the CREATE statement and all the ALTER DATABASE statements, down to the [USE database] command.
  8. Look in the scrollbar for possible problems...  Then fix them.
  9. Run the script and see what happens.  Get coffee.  It's gonna be a while.  Call your Dad.  He misses you.


You're done.  Just in case you don't have all the same Generate Scripts options, this demo was from a SQLExpress2016 database, using all this stuff...

Microsoft SQL Server Management Studio                        14.0.17199.0
Microsoft Analysis Services Client Tools                        14.0.1008.227
Microsoft Data Access Components (MDAC)                        10.0.16299.15
Microsoft MSXML                        3.0 4.0 6.0
Microsoft Internet Explorer                        9.11.16299.0
Microsoft .NET Framework                        4.0.30319.42000
Operating System                        6.3.16299



Thursday, February 22, 2018

Fix for nav-tabs Stop Working After jQuery Update


If your tabbed notebooks stopped working after a jQuery update then here's the fix.

First, you'll need some classes you didn't have before in your site.css


    .nav-tabs { border-bottom: 2px solid #DDD; }
    .nav-tabs > li > a {
        border: none;
        color: #666;
    }
    .nav-tabs > li.nav-item > a,
    .nav-tabs > li.nav-item > a:hover {
        border: none;
        color: #4285F4 !important;
        background: transparent;
        position: relative;
    }
    .nav-tabs > li.nav-item > a::after {
        content: "";
        background: #4285F4;
        height: 2px;
        position: absolute;
        width: 100%;
        left: 0px;
        bottom: -1px;
        transition: all 250ms ease 0s;
        transform: scale(0);
    }
    .nav-tabs > li.nav-item > a.active::after,
    .nav-tabs > li.nav-item:hover > a::after {
        transform: scale(1);
    }

    .card {
        box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.3);
    }

Then you'll need to rearrange things on your tab sets.
Use the following rules.
  1. Tabs
    1. <ul> needs to be in a <div class="nav navbar">
    2. <ul> needs <class="nav nav-tabs">
    3. <li> no longer gets class="active"
    4. <li> needs class="nav-item"
    5. <a> tags in your <li> now get class="active show" if they are the active tab.
  2. Tab Panes
    1. tab panes go in a <div class="tab-content">
    2. <div>s needs a class="tab-pane"
    3. in <div> tags, fade needs in or your div will not show.
Here is a sample page:

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Index</h2>
<h2>Tabsperimentation</h2>
    <div class="nav navbar-default">
        <ul class="nav nav-tabs">
            <li class="nav-item"><a class="active show" data-toggle="tab" href="#TabA">GO TO TAB A</a></li>
            <li class="nav-item"><a data-toggle="tab" href="#TabB">GO TO TAB B</a></li>
            <li class="nav-item"><a data-toggle="tab" href="#TabC">GO TO TAB C</a></li>
        </ul>
    </div>

    <div class="tab-content">
        <div id="TabA" class="tab-pane fade in active">
            THIS IS TAB A
        </div>

        <div id="TabB" class="tab-pane fade in">
            THIS IS TAB B
        </div>

        <div id="TabC" class="tab-pane fade in">
            THIS IS TAB C
        </div>
    </div>









Monday, November 27, 2017

Absolutely no Fixed Bid Contracts - Ever!

I got a job from a client and it was a fixed bid.  We pay you x dollars and you finish the work.
BUT...

  • The scope was ill-defined
    • the "spec" for the project was "replace our existing system", not an objective set of criteria.  Therefore any variation between their old system and the new one could be considered incorrect.
    • If there are features that we cant see from the 300 screen shots we have, then we'll have to do them all to be "finished"
    • because there is no objective spec, this will end up where all fixed bid contracts end up
      • the client will expect us to "finish" the project forever, because if they ever accept the work, then they will have to pay more for changes.
      • the client will always have a giant list of 'fixes' whenever we show them the completed work.
      • we will continue to push them to go live, and they will have every inclination to manufacture more and more changes, even if they are not in the original project.
  • The estimate was based on a very simplified version of the work
    • we showed the client a mockup with all the bells and whistles, and gave them an estimate.
    • the client liked it, but wanted the work much, much cheaper.
    • we offered a simplified approach to lower the cost.
    • they didn't really listen and kept expecting everything at the lower cost.

This week I will finish the project.  I will build it to the demo server and the client will look at it.  We have exhausted ALL the hours assigned to the work.  They are going to have a list of things they want "fixed" before going live.  At that point we will want more money, but as far as they are concerned, it's a fixed bid.  They get whatever they want for the agreed price. 

Welcome to slavery.  Working free forever and never getting paid again.

Unless a project is less than 10 hours, NEVER accept a fixed bid contract.  It's a no-win scenario.

...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, November 9, 2017

MVC ActionLink will not Accept Markup (easy fix!)


I needed to make a button that included a glyphicon.  The glyphicon looked like this:  
<i class="fa fa-plus"></i>  
If you use this in @Html.ActionLink() you'll see the markup in your page, not the glyphicon.

There is a way around this:

Replace your @Html.ActionLink() with this...

<a href="@Url.Action("Index","Customers",new { CompanyID = Model.UniqueId }, null)" class="btn btn-warning"><i class="fa fa-plus"></i></a>

Yeah, it's a lot more text, but Url.Action() does most of the heavy lifting.  Another requirement I had was that the QA website URL includes a folder. i.e. in development the URL is http://localhost:34238/ and in QA it's http://website.com/projectname/.  This prevents me from just hard coding the link to /Customers/Index...  Url.Action takes care of this as well.



Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Thursday, September 21, 2017

Cool Little Batch File to Log Your Crappy ISP

 Tried this in Windows 10.  I just spent all day with the internet winking on and off, and wanted to get a feeling for the extent of the outages.  Also sometimes they were hard down, and other times the DNS servers just stopped working.

Enjoy...


@echo off
cls
set Address=google.com
set ThisDate=%date%A
echo %ThisDate%

:Loop
timeout /t 60

if  "%date%" NEQ "%ThisDate%" (
echo %date% >>logfile.log
set ThisDate=%date%
echo %ThisDate%
)

echo %time% >>logfile.log

echo Pinging %Address%
%SystemRoot%\system32\ping.exe -n 1 %Address% | %SystemRoot%\system32\find.exe "TTL=" > NUL >> logfile.log

if %ERRORLEVEL% EQU 0 goto :Loop

echo Error Detected! >>logfile.log
echo Error Detected! 

echo Trace route %Address% at %date% %time% >> logfile.log
tracert %Address% >> logfile.log

echo .
echo . >> logfile.log

goto Loop
pause Somehow, I got out of the loop


Of course, you can ping another site besides Google, and you can test more or less frequently than 60 seconds.

The log file grows forever unless you rename it, and looks a lot like this:
Thu 09/21/2017 
15:55:28.70 
Error Detected! 
Trace route google.com at Thu 09/21/2017 15:55:40.74 
Unable to resolve target system name google.com.
. 
15:56:10.16 
Error Detected! 
Trace route google.com at Thu 09/21/2017 15:56:22.19 
Unable to resolve target system name google.com.
. 
15:56:52.15 
Reply from 172.217.4.142: bytes=32 time=18ms TTL=54
15:57:22.17 
Reply from 172.217.4.142: bytes=32 time=18ms TTL=54
15:57:52.13 
Reply from 172.217.4.142: bytes=32 time=18ms TTL=54
15:58:22.11 
Reply from 172.217.4.142: bytes=32 time=17ms TTL=54
15:58:52.18 
Reply from 172.217.4.142: bytes=32 time=18ms TTL=54



Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Friday, June 23, 2017

Found on Job Postings...

"must be familiar with Software Development Life Cycle"... 

No two companies use the same one, and most exclude several steps from the map. For instance, if your SDLC does not include the eventual phase-out of your application, then it's incomplete. It's ludicrous to think that any software we develop is going to perform forever, so the phase out - especially of corporate software - is a reasonable part of the plan.  

 
...

Bryan Valencia is a contributing editor and founder of Visual Studio Journey.  He owns and operates Software Services, a web design and hosting company in Manteca, California.

Share This!

Contact Us

Name

Email *

Message *