Ok, assuming this markup?
<div style="width:50%">
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" DataKeyNames="ID" CssClass="table table-hover">
<Columns>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" SortExpression="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
<asp:TemplateField HeaderText="Select">
<ItemTemplate>
<asp:Button ID="cmdSel" runat="server" Text="Select"
onclick="cmdSel_Click"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Ok, our code to fill this out looks like this:
Sub LoadGrid()
Using cmdSQL As New SqlCommand("SELECT ID, FirstName, LastName, HotelName, City from tblHotels",
New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
Dim rstTable As New DataTable
rstTable.Load(cmdSQL.ExecuteReader)
If rstTable.Columns.Contains("City") = False Then
GridView1.Columns(3).Visible = False
End If
GridView1.DataSource = rstTable
GridView1.DataBind()
End Using
End Sub
So the output is this:

But, if I say leave out the city column, with this sql?
SELECT ID, FirstName, LastName, HotelName from tblHotels
Then the output is this:

There no easy way to reference by column name - so often some will cook up a little helper routine to work by column name - but regardless, you can check if the column exists in the data soruce - if you set Visible=False for that column, it will not be rendered at all, and hence the Eval() expression will not run either.