Creating a custom map with MapBox and TileMill from SQL 2005 - sql-server-2005

I have a requirement to build a web application with geo-mapping that will display pins on a map and the data comes from my sql 2005 database. This intranet application will be hosted on our secure server and will not have access to any outside resources and cannot use any external api's.
After searching on the internet, I found that I can use leaflet.js and mapbox to handle this although I have to move all of the files locally. I also need to create a custom map with TileMill and then copy the tiles to my applications. I tried to create my custom map but I cannot create any layers because it is asking for a datasource to a csv file or sqllite and I need to pass the data from my sql 2005 database. Is it possible to create a custom map with tilemill and provide my own datasource? Am I going about this the right way? Is there a better way to create a geo-mapping application that has to be accessed locally?
Thanks

Rob, I am sure there is a better way to do this but this is the way I implemented it.
The solution I am about to give you should allow you to add markers to a Mapbox map (search "omnivore mapbox" for web application CSV import equivalent of TileMill add data source feature) that can be accessed through your web application and that gets its data from a CSV file generated from a GridView connected to a MS SQL database.
I had at the same problem, data is in SQL 2008 and I need to use it to create a map.
Mapbox required CSV or POSTGRESQL to display pins but I did not have a POSTGRESQL server setup anywhere.
Here is what I did:
(note that I am using C# and creating a ASP NET web application)
Create an empty ASPX page, let's call it DataGridView.aspx
Add a GridView
Link that GridView to your SQL data source
Create a button, call it "Refresh CSV"
Double click on it to automatically create an event for that button.
In the code for the event for that button, use this piece of code:
protected void Button1_Click(object sender, EventArgs e)
{
GridView1.AllowPaging = false;
GridView1.DataBind();
StringBuilder sb = new StringBuilder();
for (int k = 0; k < GridView1.Columns.Count; k++)
{
if(k==0) // little trick to avoid comma at the end of the line
{
sb.Append(GridView1.Columns[k].HeaderText);
continue;
}
//add separator
sb.Append(',' + GridView1.Columns[k].HeaderText);
}
//append new line
sb.Append("\r\n");
for (int i = 0; i < GridView1.Rows.Count; i++)
{
for (int k = 0; k < GridView1.Columns.Count ; k++)
{
if (k == 0) // little trick to avoid comma at the end of the line
{
sb.Append(GridView1.Rows[i].Cells[k].Text);
continue;
}
//add separator
sb.Append(','+GridView1.Rows[i].Cells[k].Text );
}
//append new line
sb.Append("\r\n");
}
string a= string.Empty;
StreamWriter yourStream = File.CreateText(Server.MapPath("~/CSVExport.csv"));
a = sb.ToString()+"\r\n"; //formatting text based on poeition
yourStream.Write(a);
yourStream.Close();
}
Don't forget to have these at the beginning of your DataGridView.aspx.cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Text;
On the root of your web application, create an empty file, name it "CSVExport.csv".
This is going to hold your GridView Data formatted as a CSV.
Now every time you click that button, it should update your CSVExport.csv file.
To check if everything displays correctly, launch TileMill and run (debug run locally) your website.
Go to [localhost:whateverthatportnumberis]/DataGridView.aspx
Click on the button.
Open CSVExport.csv to check if your file has been updated (you should see your data in CSV file format.)
Now, without stopping your local website test, go ahead and use the link to the CSV file in TileMill
[localhost:whateverthatportnumberis]/CSVExport.csv
If your CSVExport.csv file is formatted correctly, you should see the markers being displayed.
This should answer your question on how to get your data from SQL to a CSV format that can be used by Mapbox.
Your question becomes ambiguous here when you say: " Is there a better way to create a geo-mapping application that has to be accessed locally?". So I am going to stop here.
Again, the solution I just gave you should allow you to add markers to a Mapbox map (search "omnivore mapbox" for web application CSV import equivalent of TileMill add data source feature) that can be accessed through your web application and that gets its data from a CSV file generated from a GridView connected to a MS SQL database.

One way is to create your custom map in TileMill, without the data in your SQL 2005 database, and to export it as a mbtiles file which you can afterwards host on mapbox.
Use this map as the baselayer in leaflet.js, and add your markers dynamically loaded via AJAX from a REST API accessing your SQL database.

Related

How to access files stored in SQL Server's FileTable?

As I know SQL Server since version 2012 has a new feature, FileTable. It allows us to store files in the file system and to use them from T-SQL.
I am trying to use this feature and I have no idea how to do it properly.
Generally, I don't know how to access files stored in the file table. Let's suppose I have asp.net MVC app and there are a lot of images which I show on web pages in img tags. I would like to store these images in Filetable and access them as files from the filesystem. But I don't know where these files are stored and how to use them as files. Now my images are stored in web application directory in folder images and I write something like this:
<img src='/images/mypicture.png' />
And if I move my images to file table what I should write in src?
<img src='path-toimage-in-filetable' />
I don't think you still need this, anyways I'll post my answer for anyone else interested.
First, a filetable still being a table, so, if you want to access to data from it you need to use a Select SQL statement. So you'd need something like:
select name, file_stream from filetable_name
where
name = 'file_name',
file_type = 'file_extension'
just execute an statement like this in your asp.net app, then fetch the results and use the file_stream column to get the binary data of the stored file. If you want to retrieve the file from HTML, first you need to create an action in your controller, which will return the retrieved file:
public ActionResult GetFile(){
..
return File(file.file_stream,file.file_type);
}
After this, put in you HTML tag something like:
<img src="/controller/GetFile" />
hope this could help!
If you want to know the schema of a filetable see
here
I assume by FileTable you actually mean FileStream. A couple notes about that:
This feature is best used if your files are actually files
The files should be, on average, greater than 1mb - although there can be exceptions to this rule, if they're smaller than 1mb on average, you may be better off using a VARBINARY(MAX) or XML data type as appropriate. If your images are very small on average (only a few KB), consider using a VARBINARY(MAX) column.
Accessing these files will require an open transaction and that the database is properly configured for FILESTREAM
You can get some significant advantages bypassing the normal SQL engine/database file method of data access by telling SQL Server that you want to access the file directly, however it's not meant for directly accessing the file on the file system and attempting to do so can break SQL's management of these files (transactional consistency, tracking, locking, etc.).
It's pretty likely that your use case here would be better served by using a CDN and storing image URLs in the table if you really need SQL for this. You can use FILESTREAM to do this (see code sample below for one implementation), but you'll be hammering your SQL server for every request unless you store the images somewhere else anyway that the browser can properly cache (my example doesn't do that) - and if you store them somewhere else for rendering int he browser you might as well store them there to begin with (you won't have transactional consistency for those images once they're copied to some other drive/disk/location anyway).
With all that said, here's an example of how you'd access the FILESTREAM data using ADO.NET:
public static string connectionString = ...; // get your connection string from encrypted config
// assumes your FILESTREAM data column is called Img in a table called ImageTable
const string sql = #"
SELECT
Img.PathName(),
GET_FILESTREAM_TRANSACTION_CONTEXT()
FROM ImageTagble
WHERE ImageId = #id";
public string RetreiveImage(int id)
{
string serverPath;
byte[] txnToken;
string base64ImageData = null;
using (var ts = new TransactionScope())
{
using (var conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add("#id", SqlDbType.Int).Value = id;
using (SqlDataReader rdr = cmd.ExecuteReader())
{
rdr.Read();
serverPath = rdr.GetSqlString(0).Value;
txnToken = rdr.GetSqlBinary(1).Value;
}
}
using (var sfs = new SqlFileStream(serverPath, txnToken, FileAccess.Read))
{
// sfs will now work basically like a FileStream. You can either copy it locally or return it as a base64 encoded string
using (var ms = new MemoryStream())
{
sfs.CopyTo(ms);
base64ImageData = Convert.ToBase64String(ms.ToArray());
}
}
}
ts.Complete();
// assume this is PNG image data, replace PNG with JPG etc. as appropraite. Might store in table if it will vary...
return "data:img/png;base64," + base64ImageData;
}
}
Obviously, if you have lots of images to handle like this this is not an ideal method - don't try to make an instance of SQL server into what you should be using a CDN for.... However, if you have other really good reasons, you should try to grab as many images as possible in a single request/transaction (e.g. if you know you're displaying 50 images on a page, get all 50 with a single transaction scope, don't use 50 transaction scopes - this code won't handle that).

File download control - delete file without validation?

Hello XPages programmers.
I work on a simple XPages File Library.
To achieve that i use FileUpload control with FileDownload control.
When i create a new file, i enter its name, and select a file.
I set that uploading a file won't activate a validation, so i can attach a file without a specified name. Additionally i set it to do fullrefresh, so uploading a file takes place in an instant and a file is visible in FileDownload control.
Problem occurs, when i want to delete that attachment using garbage icon of FileDownload - i can't set it to run without walidation.
Is there any workaround avaiable?
Any help will be appreciated.
I used the workaround Mark Leusink suggested - created a simmilar button (used image from filedownload control) and then set it for full refresh with process data without validation property.
Code in JSSS
function deleteAttachments()
{
var attList = dDocument.getAttachmentList("Document_Attachment");
for(var i=0; i<attList.size(); i++)
{
var att:String = attList[i];
dDocument.removeAttachment("Document_Attachment", att.getName() );
}
}
Surely it can be used for delete a specific attachment by getting attachment name from rowdata in a repeater and use DATASOURCE.removeAttachment method.
Thanks for your support!

ObjectARX SDK for c#

For last two days I have looking for sample code with steps which may help me to understand the Autocad API. so I can use the code in C#.
[CommandMethod("LISTGEn")]
public static void ListEntities()
{
Document acDoc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument;
Database acCurDb = acDoc.Database;
using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
{
// Open the Block table record for read
BlockTable acBlkTbl;
acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId,OpenMode.ForRead) as BlockTable;
// Open the Block table record Model space for read
BlockTableRecord acBlkTblRec;
acBlkTblRec = acTrans.GetObject(acBlkTbl[BlockTableRecord.ModelSpace],OpenMode.ForRead) as BlockTableRecord;
int nCnt = 0;
acDoc.Editor.WriteMessage("\nModel space objects: ");
// Step through each object in Model space and
// display the type of object found
foreach (ObjectId acObjId in acBlkTblRec)
{
acDoc.Editor.WriteMessage("\n" + acObjId.ObjectClass.DxfName);
nCnt = nCnt + 1;
}
acDoc.Editor.WriteMessage(nCnt.ToString());
// If no objects are found then display a message
if (nCnt == 0)
{
acDoc.Editor.WriteMessage("\n No objects found");
}
// Dispose of the transaction
}
}
I can run the above code, but it's not functioning properly. It's difficult for me to understand how to get it work with Autocad. I have OjectARX SDK referenced,
I am working with VS2010 and Autocad 2012. Thank You for your help.
Ok, I got it only thing that is being required
1.) is to create a class library
2.) Then need to enter the above code in the class.
3.) Build your project by pressing F5.
4.) A DLL will be created in the bin/debug/ folder of your project
5.) Open Autocad.
6.) Write netload command.
7.) Select the DLL created and then write command "LISTGEN" and than kaboom it will show all the objects in your project.
To avoid having to manually netload your dll, you can use a temporary fix for debugging and write a lisp file to do it for you
(Command "netload" "path/to/your/.dll")\n
Or you can use \\
Take a look at my github. The link is on my profile. Look over the reference library, it's highly simplified for object model manipulation.
If you have any questions feel free to email me.

Photoshop: get slices via SDK and copy content

I want to copy the content of the current seleced slice in my photoshop cs3 document to a new document using an own written script/plugin.
Currently, I do this manually: I select the slice, press ctrl+c (copy), create a new document and then I press ctrl+v (paste).
What I have so far is the automation plugin example 'MakeNew' that creates a new document:
static SPErr MakeNewDocument (void)
{
SPErr error = kSPNoError;
PIActionDescriptor descriptor = NULL;
error = sPSActionDescriptor->Make (&descriptor);
...
}
Any Idea how I can access the current selected slice and copy the content to the new document?
Thanks for hints.
Looks like there is no way to get the slices even via SDK in CS3.

How to link a PDF Document to a Record using Visual Studio LightSwitch 2011?

I'm Stuck the following problem: How can I link a PDF Document to a Record in a Data Grid using Visual Studio LightSwitch 2011 and Visual Basic?
Any help would be awesome, thanks!
Here's the simplest way to do this: add a custom command to the Command Bar of the Data Grid Row for your Data Grid. In this example I'm calling the command Open PDF File. Then add this code to Execute code for the command:
partial void OpenPDFFile_Execute()
{
const string LOCAL_SERVER_PDF_DIR = #"\\MyServer\PDFs\";
const string WEB_SERVER_PDF_DIR = "http://myweb.server/PDFs/";
const string PDF_SUFFIX = ".pdf"; //assumes you do not include the extension in the db field value
if (AutomationFactory.IsAvailable)
{
//if the AutomationFactory is available, this is a desktop deployment
//use the shell to open a PDF file from the local network
dynamic shell = AutomationFactory.CreateObject("Shell.Application");
string filePath = LOCAL_SERVER_PDF_DIR + this.PDFFiles.SelectedItem.FileName + PDF_SUFFIX;
shell.ShellExecute(filePath);
}
else
{
//otherwise this must be a web deployment
//in order to make this work you must add a reference to System.Windows.Browser
//to the Client project of your LS solution
var uri = new Uri(WEB_SERVER_PDF_DIR + this.PDFFiles.SelectedItem.FileName + PDF_SUFFIX);
HtmlPage.Window.Navigate(uri, "_blank");
}
}
You will need to add the following imports to the top of your user code file to make this code compile:
using System.Runtime.InteropServices.Automation;
using System.Windows.Browser;
I should mention that you need a directory to server the PDFs up from. This example is flexible with respect to deployment, because it handles both desktop and web configurations. Since you'll need to set up the PDF directoy, you may want to just handle one configuration option to simply things (or you could expose the same PDF directory over http and as a local network share).
You may also want to present this as a true link instead of a button. In order to do this, you'll need a custom SilverLight control. In any case, I would recommend implementing the PDF link using a button first. You can then move this same code to a link event handler as a separate project if that is worth spending time on.