Mam ciąg połączenia i chcę mieć możliwość podglądu na przykład "Źródło danych". Czy istnieje parser, czy muszę przeszukiwać ciąg?Czy istnieje parser ciągów połączenia w języku C#?
Odpowiedz
Tak, istnieje klasa System.Data.Common.DbConnectionStringBuilder
.
klasie DbConnectionStringBuilder zapewnia klasę bazową, z której silnie wpisany ciąg połączenia budowniczych (SqlConnectionStringBuilder, OleDbConnectionStringBuilder, i tak dalej) wyprowadzić. Łańcuch połączenia konstruktorów umożliwia programistom programowe tworzenie syntaktycznie poprawnych ciągów połączenia i analizowanie i odbudowywanie istniejących połączeń ciągów.
podklas miejsca to:
System.Data.EntityClient.EntityConnectionStringBuilder
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
Na przykład, aby "wyglądać źródła danych" z ciągu połączenia SQL Server, można zrobić:
var builder = new SqlConnectionStringBuilder(connectionString);
var dataSource = builder.DataSource;
Użyj SqlConnectionStringBuilder Niestety, będziesz musiał użyć specyficznego dla DB ConnectionStringBuilder jako ciągów połączenia diffe r.
Użytkownik chce użyć DbProviderFactory.CreateConnectionStringBuilder(), który zapewnia konstruktor połączenia/parser specyficzny dla danego konektora, ale nie wymaga używania żadnych klas specyficznych dla łącznika.
Tak, możesz to zrobić, używając klas ConnectionStringBuilder. Oto lista dostępnych wdrożeń DbConnectionStringBuilder standardowych dostawców danych:
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
oto próbka przykładem parse ciąg połączenia i wyświetli jego elementy.
string conString = @"Data Source=.\sqlexpress;" +
"Database=Northwind;Integrated Security=SSPI;" +
"Min Pool Size=5;Max Pool Size=15;Connection Reset=True;" +
"Connection Lifetime=600;";
// Parse the SQL Server connection string and display it's properties
SqlConnectionStringBuilder objSB1 = new SqlConnectionStringBuilder(conString);
Response.Write("<b>Parsed SQL Connection String Parameters:</b>");
Response.Write(" <br/> Database Source = " + objSB1.DataSource);
Response.Write(" <br/> Database = " + objSB1.InitialCatalog);
Response.Write(" <br/> Use Integrated Security = " + objSB1.IntegratedSecurity);
Response.Write(" <br/> Min Pool Size = " + objSB1.MinPoolSize);
Response.Write(" <br/> Max Pool Size = " + objSB1.MaxPoolSize);
Response.Write(" <br/> Lifetime = " + objSB1.LoadBalanceTimeout);
Istnieją specyficzne sprzedawca ciąg połączenia budowniczych z różnych dostawców, jak SqlConnectionStringBuilder
MySqlConnectionStringBuilder
, SQLiteConnectionStringBuilder
itp (niestety nie ma public interface z MS tym razem). W przeciwnym razie masz DbProviderFactory.CreateConnectionStringBuilder, który da ci alternatywny sposób, aby napisać to, co nie jest agnostyczne. Będziesz musiał określić dostawcę w pliku konfiguracyjnym i mieć odpowiednią wersję biblioteki dll. Na przykład:
var c = "server=localhost;User Id=root;database=ppp";
var f = DbProviderFactories.GetFactory("MySql.Data.MySqlClient"); //your provider
var b = f.CreateConnectionStringBuilder();
b.ConnectionString = c;
var s = b["data source"];
var d = b["database"];
Raz napisałem sobie ręczne parsowanie, które nie sprawiało mi żadnych kłopotów. Byłoby trywialne, aby rozszerzyć to, aby podać informacje na temat innych parametrów (teraz jest to tylko dla prostych rzeczy, takich jak nazwa bazy danych, źródło danych, nazwa użytkownika i hasło). Tak lub inaczej:
static readonly string[] serverAliases = { "server", "host", "data source", "datasource", "address",
"addr", "network address" };
static readonly string[] databaseAliases = { "database", "initial catalog" };
static readonly string[] usernameAliases = { "user id", "uid", "username", "user name", "user" };
static readonly string[] passwordAliases = { "password", "pwd" };
public static string GetPassword(string connectionString)
{
return GetValue(connectionString, passwordAliases);
}
public static string GetUsername(string connectionString)
{
return GetValue(connectionString, usernameAliases);
}
public static string GetDatabaseName(string connectionString)
{
return GetValue(connectionString, databaseAliases);
}
public static string GetServerName(string connectionString)
{
return GetValue(connectionString, serverAliases);
}
static string GetValue(string connectionString, params string[] keyAliases)
{
var keyValuePairs = connectionString.Split(';')
.Where(kvp => kvp.Contains('='))
.Select(kvp => kvp.Split(new char[] { '=' }, 2))
.ToDictionary(kvp => kvp[0].Trim(),
kvp => kvp[1].Trim(),
StringComparer.InvariantCultureIgnoreCase);
foreach (var alias in keyAliases)
{
string value;
if (keyValuePairs.TryGetValue(alias, out value))
return value;
}
return string.Empty;
}
Do tego nie potrzeba niczego specjalnego w pliku konfiguracyjnym lub jakiejkolwiek dll w ogóle. Contains
w klauzuli Where
jest ważna tylko wtedy, gdy trzeba ominąć źle sformatowane ciągi połączeń, takie jak server = localhost;pp;
, gdzie pp
nie dodaje nic.Zachowywać się jak normalne budowniczych (które wybuchają w tych przypadkach) zmienić Where
do
.Where(kvp => !string.IsNullOrWhitespace(kvp))
Oto kilka linijek kodu, które zanalizować dowolny ciąg połączenia do słownika:
Dictionary<string, string> connStringParts = connString.Split(';')
.Select(t => t.Split(new char[] { '=' }, 2))
.ToDictionary(t => t[0].Trim(), t => t[1].Trim(), StringComparer.InvariantCultureIgnoreCase);
a następnie mogą uzyskać dostęp do każdej części:
string dataSource = connStringParts["Data Source"];
Inteligentne, jedyne, co chciałbym zmienić, to "StringSplitOptions.RemoveEmptyEntries" do pierwszego podziału, ponieważ spowoduje on wyjątek 'IndexOutOfRange', jeśli istnieje końcowe'; ' –
To działa, ale konstruktory połączeń są bardziej niezawodne . Kod taki jak ten spowoduje odrzucanie wyjątków niskiego poziomu zamiast bardziej znaczących błędów analizy w przypadku nieprawidłowych ciągów połączeń. – Sam
Pomogło mi to przetworzyć ciąg połączenia ADO, tak żebym mógł zbudować odpowiednik 'SqlConnection' z' SqlConnectionStringBuilder'. –
można użyć DbConnectionStringBuilder, i nie trzeba żadnego konkretnego dostawcy:
Poniższy kod:
var cnstr = "Data Source=data source value;Server=ServerValue";
var builder = new DbConnectionStringBuilder();
builder.ConnectionString = cnstr;
Console.WriteLine("Data Source: {0}", builder["Data Source"]);
Console.WriteLine("Server: {0}", builder["Server"]);
Wyjścia pocieszyć:
Data Source: data source value
Server: ServerValue
EDIT:
Od DbConnectionStringBuilder implementuje IDictionary można wyliczyć parametry ciągu połączenia:
foreach (KeyValuePair<string, object> kv in builder)
{
Console.WriteLine("{0}: {1}", kv.Key, kv.Value);
}
Zakłada to, że już wiesz, że ciąg połączenia ma wartość "Źródło danych" itp., Co nie zawsze jest prawdą, jak wspomniano powyżej w http://stackoverflow.com/a/15529085/534109. –
Moja odpowiedź dodaje konkretnie, co op pyta: "Chcę mieć możliwość podglądu na przykład" Źródło danych "' –
Edytowałem to, aby pokazać wszystkie parametry ciągu połączenia. –
Więc znalazłem wszystko, co istnieje odpowiedzi były mniej lub bardziej błędne. Skończyło się następujące rozwiązanie trywialne:
class ConnectionStringParser: DbConnectionStringBuilder {
ConnectionStringParser(string c) { Connection = c; }
public override bool ShouldSerialize(string keyword) => true;
}
Parser jest w DbConnectionStringBuilder i dość dużo łatwo dotrzeć. Jedyną głupią rzeczą, którą musimy zrobić, to ustawić opcję ShouldSerialize tak, aby zawsze zwracała wartość true, aby zapobiec utracie komponentów podczas próby oblężenia arbitralnych ciągów połączeń.
Co było nie tak z istniejącymi odpowiedziami? Albo co rozwiązuje twoje rozwiązanie. Pomocne byłoby wyjaśnienie. – nawfal
- 1. Czy istnieje parser CSS dla C#?
- 2. Czy istnieje parser .NET CQL?
- 3. Czy istnieje parser wieloczęściowy/formularz danych w C# - (NO ASP)
- 4. Czy istnieje odpowiednik Groovy w języku C#?
- 5. Czy istnieje klasa wirtualna w języku C#?
- 6. Czy istnieje metoda "upto" w języku C#?
- 7. Niestandardowe porównanie ciągów w języku C#
- 8. Czy istnieje metoda "podzielonej listy" w języku C#?
- 9. Czy istnieje parser Java dla języka Java?
- 10. Odczytywanie ciągów połączenia z konfiguracji ciągów połączenia internetowego Azure
- 11. LISP Parser C++
- 12. Jak sprawdzić, czy plik istnieje w Qt w języku C++
- 13. Jawny odpowiednik ciągów znaków w języku C# z @
- 14. Szyfrowanie ciągów w języku C# i Objective c
- 15. Zalecany parser JSON w C?
- 16. Czy istnieje zasób tablicy ciągów dla programu Visual C# 2005?
- 17. Czy istnieje odpowiednik w języku C# do tego kodu Java?
- 18. Czy istnieje implementacja selektorów Sizzle/jQuery w języku C#?
- 19. Jak ustalić, czy podkatalog istnieje w języku C#?
- 20. Czy istnieje sposób na znalezienie ID Teamviewer w języku C#?
- 21. Czy istnieje przenośny sposób kopiowania bloku pamięci w języku C#?
- 22. Czy istnieje delegat dostępny dla właściwości w języku C#?
- 23. Czy istnieje odpowiednik metody skanowania C w języku Java?
- 24. Czy istnieje kontrola do wizualizacji topologii siatki w języku C#?
- 25. Czy istnieje instrukcja VB.NET "With" w języku C#?
- 26. Parsowanie ciągu znaków w języku C#; czy istnieje czystszy sposób?
- 27. Czy istnieje już funkcja warunkowego Zip w języku C#?
- 28. Czy istnieje odpowiednik frexp w języku Java?
- 29. Czy istnieje jakiś parser JSDoc Open Source napisany w JavaScript?
- 30. Prosty C XML parser
@Icarus nie jest tak naprawdę, ponieważ słownik porównywania słów jest "StringComparer.InvariantCultureIgnoreCase". Zobacz przeciążenie 'ToDictionary' – nawfal
Tak, masz rację, właśnie napisałem szybki test. Usunie mój oryginalny komentarz, ponieważ jest nieprawidłowy. – Icarus
Twoja metoda GetValue() nie będzie działać w przypadkach, gdy użytkownik ma na przykład hasło ""; "" lub "" = "" w swoim haśle. Napisałem podobną implementację i dowiedziałem się, że to nie działa na swój sposób. Gosh, parsowanie połączenia jest w rzeczywistości o wiele trudniejsze, niż myślałem! –