How to get Database names from given Sql Server in LINQ - asp.net

I have DropDownList displays all server present in my network
I want to populate the databse names when i changed it into another dropdown
I want a LINQ query to get this.

See the question here on how to get the list of databases available to the logged-in user:
SELECT name
FROM sys.sysdatabases
WHERE HAS_DBACCESS(name) = 1
Implementing this into LINQ requires you to publish the sysdatabases view into your own view. I would recommend creating a view for the job in one of the databases:
CREATE VIEW [dbo].[vewDatabases]
AS
SELECT name
FROM sys.sysdatabases
WHERE HAS_DBACCESS(name) = 1
GO
Add this to your LINQ data model, and you will be able to select from it like so [c#]:
var databaseNames = serverDataContext.vewDatabases.Select(a => a.name);
You can then populate the DropDownList with the contents of databaseNames.

I don't think this is a job for Linq2SQL (though I'm not overly familiar with it).
Basically, I think you can get the results you want by looking at one of the SYS_ tables, or a SP_ stored procedure. Can't remember which - been a while since I did anything with SQL Server.

Try code below:
protected void ddList_SelectedIndexChanged(object sender, EventArgs e)
{
PopulateDatabaseDropDown(ddList.SelectedItem.Text);
}
private void PopulateDatabaseDropDown(string server)
{
ddDatabase.DataSource = DatabaseName(server);
ddDatabase.DataValueField = "DatabaseId";
ddDatabase.DataTextField = "Name";
ddDatabase.DataBind();
}
private DataBase[] DatabaseName(string serverName)
{
List<DataBase> data = new List<DataBase>();
System.Data.Linq.DataContext db = new System.Data.Linq.DataContext("Data Source="+serverName+";Initial Catalog=master;Integrated Security=SSPI");
var dbName = db.ExecuteQuery<DataBase>("select database_id, [name] from sys.databases").AsEnumerable();
foreach (var item in dbName)
data.Add(new DataBase() { DatabaseId = item.DatabaseId, Name = item.Name });
return data.ToArray();
}
}
public class DataBase
{
public string Name { get; set; }
public int DatabaseId { get; set; }
}

Related

Need help understanding API and LINQ

I'm trying to set up an API for a system I'm working on, but the LINQ seems to not grab the parameters.
A bit of background: During covid I've been working with a local business owner to develop an info system for his business. So far, everything has been kept in the browser, but now we want to create a small windows form application the users can download instead of using the browser. The application will be much smaller in scope than the full site, but I don't want the SQL connection in the form.
So I guess my first question is, am I being overly cautious at not wanting the SQL connector in the client and wanting them to connect to the database, via an API, or is it safe enough to add the connection and calls directly in the application (I know how to do this, it's the API part I can't figure out). I'm thinking about it from a security point of view - would the users be able to find the connection and potentially do harm to my database by having it straight in the application or is it safe there?
If using API calls is the proper way to go, that leads me to my second question. How do I configure it properly?
This is my table (I've been following the Microsoft ToDoItems tutorials):
CREATE TABLE [dbo].[TodoItems] (
[Id] [int] identity(1,1) NOT NULL,
[Name] [nvarchar](50) NULL,
[IsComplete] [bit] NULL,
[Secret] [nvarchar](10) NULL
) ON [PRIMARY]
GO
My test form has a single button, which when pressed calls this method:
static async Task RunAsync()
{
// Update port # in the following line.
client.BaseAddress = new Uri("https://localhost:7217/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
try
{
// Create a new product
TodoItem product = new TodoItem
{
Name = "Gizmo",
IsComplete = false,
Secret = "false"
};
var url = await CreateProductAsync(product);
Console.WriteLine($"Created at {url}");
// Get the product
product = await GetProductAsync(url.PathAndQuery);
ShowProduct(product);
// Update the product
Console.WriteLine("Updating IsCompleted...");
product.IsComplete = true;
await UpdateProductAsync(product);
// Get the updated product
product = await GetProductAsync(url.PathAndQuery);
ShowProduct(product);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
My ToDoItem class looks like this:
public class TodoItem
{
public long Id { get; set; }
public string Name { get; set; }
public bool IsComplete { get; set; }
public string Secret { get; set; }
}
My first issue is creating the ToDoItem. This method should do the trick:
static async Task<Uri> CreateProductAsync(TodoItem product)
{
HttpResponseMessage response = await client.PostAsJsonAsync(
"api/todoitems", product);
response.EnsureSuccessStatusCode();
// return URI of the created resource.
return response.Headers.Location;
}
However, when I run the method my API logs this error and nothing is posted to the database:
Executed DbCommand (46ms) [Parameters=[#p0='?' (DbType = Boolean), #p1='?' (Size = 4000), #p2='?' (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
INSERT INTO [TodoItems] ([IsComplete], [Name], [Secret])
VALUES (#p0, #p1, #p2);
SELECT [Id]
FROM [TodoItems]
WHERE ##ROWCOUNT = 1 AND [Id] = scope_identity();
The way I read this, and I might be wrong, the method CreateProductAsync (which gets a product with the values "Gizmo", false and "false") simply doesn't transfer the values to the API.
For reference, my API ToDoContext class look like this:
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options)
: base(options)
{
}
public DbSet<TodoItem> TodoItems { get; set; } = null!;
}
Do I need to add something to this class? I'm wholly unfamiliar with both API and LINQ, but I did figure out that changing the table name to ToDoItems made the connection for me on its own.

Web service send id to another source and return information

So I am kind of new to Web services, and I am trying to wrap my head around how it works.
Basically, I need to receive an ID from one side, pass it to another source which returns the employee information.
Now, this is what I did so far:
[WebMethod(Description = "Returns employee object for id")]
public Employee GetEmployeeById(int Id)
{
// how to ?
return new Employee( // data from outer source);
}
I see the wsdl, where you can send the id to the function.
How does the other source get the information from my service?
The another source means that anywhere you want to connect to. Maybe it's a database, other web service, or only a text file....
For example, you have a db that saves employee data. You can use Entity Framework to get employee data from db.
Like this:
[WebMethod(Description = "Returns employee object for id")]
public Employee GetEmployeeById(int Id)
{
using(var context = new MyDbContext())
{
var emp = context.Employees.Where(x => x.Id == Id).FirstOrDefault();
return emp;
}
}

Unit Test .Net on Simple EF Function

I have 3 layers in Asp.Net Web API. The controller layer, service layer and repository layer implemented using EF.
I am new to unit testing and have a simple function that gets a person by their id in the database and nothing else.
Basically the service layer calls
Unit_Work.Person_Repository.GetPersonByID(id);
and the Repository does this:
return context.chapters.Where(p=>p.chapterID==id).SingleOrDefault();
What kind of Unit Test would i write on this.
should i use the database or a mock implementation.
I thought of using Sql Server Compact populating it with a mock person and then trying to get that person by ID is this correct.?
Thanks in advance to all those that answer.
If you are using entity framework you can't unit test your data access layer.
Solution provided by Erik Alsmyr is very wrong!
Look here why - What's the point of in memory IDbSet?.
When you use in memory db sets you are running Linq to Objects. When you use EF's DbContext your Linq is converted to SQL. Those are two different things!
It is very easy to write code that will work with in memory db set (all your unit tests will pass and you will be happy) just to notice runtime error first time you try to hit database.
Let's modify this code a bit. I don't think FULLNAME should have setter if we are using FIRSTNAME, LASTNAME. It should be calculated from FIRSTNAME and LASTNAME.
class User
{
public string FIRSTNAME { get; set; }
public string LASTNAME { get; set; }
public string FULLNAME
{
get { return string.Format("{0}, {1}", LASTNAME, FIRSTNAME }
}
User(string firstName, string lastName)
{
this.FIRSTNAME = firstName;
this.LASTNAME = lastName;
}
}
Now you can write test like this and it will pass (of course after you implement it in controller)
public IMyEntities GetRepoWithUsers(params User[] users)
{
var inMemoryUsers = new InMemoryDbSet<User>();
var mockData = new Mock<IMyEntities>();
mockData.Setup(m => m.Users).Returns(inMemoryUsers);
return mockData.Object;
}
[Test]
public void GetUserByFullname()
{
var ankaArne = new User("Arne", "Anka");
var bjornBertil = new User("Bertil", "Björn");
var repo = GetRepoWithUsers(ankaArne, bjornBertil);
var usersController = new UsersController(repo);
var found = usersController.GetUser("Anka, Arne");
Assert.NotNull(found);
Assert.AreEqual("Anka", found.LASTNAME);
Assert.AreEqual("Arne", found.FIRSTNAME);
}
But when you run it against 'real' DbContext and 'real' DbSet it will throw because you can't do Linq queries on calculated properties. Only on those that are mapped to database columns. So what's the point of that test?
You can use the xml/ .csv file for data. ie, you need to fetch the ID, chapter details from the xml file inside the unit test project. Then you have to pass the id as the parameter then check the return values with the data fetch from xml file. if you dont understand let me know. You cn create unit test project by add-new project options. then on vs2010 ther r options to add xml file for fetching the data to be tested.
your 3rd question is also correct. u cn populate the data from database and check the data with the return value
I recommend mocking and injecting an Entity framework context into your repository.
We do this using something similar to http://nuget.org/packages/FakeDbSet/
Then our unit tests look like this:
[TestFixture]
class UsersControllerTester
{
private Mock<IMyEntities> mockData = null;
[SetUp]
public void Setup()
{
// Create fake data
var inMemoryUsers = new InMemoryDbSet<User>();
inMemoryUsers.Add(new User { ID = 1, FIRSTNAME = "Arne", LASTNAME = "Anka", EMAIL = "arne.anka#email.com", FULLNAME = "Anka, Arne", USERNAME = "arne.anka" });
inMemoryUsers.Add(new User { ID = 2, FIRSTNAME = "Bertil", LASTNAME = "Björn", EMAIL = "bertil.bjorn#email.com", FULLNAME = "Björn, Bertil", USERNAME = "bertil.bjorn" });
inMemoryUsers.Add(new User { ID = 3, FIRSTNAME = "Carl", LASTNAME = "Cool", EMAIL = "carl.cool#email.com", FULLNAME = "Cool, Carl", USERNAME = "carl.cool" });
inMemoryUsers.Add(new User { ID = 4, FIRSTNAME = "David", LASTNAME = "Dûsk", EMAIL = "david.dusk#email.com", FULLNAME = "Dûsk, David", USERNAME = "david.dusk" });
// Create mock unit of work
mockData = new Mock<IMyEntities>();
mockData.Setup(m => m.Users).Returns(inMemoryUsers);
}
[Test]
public void GetUser()
{
// Test
var usersController = new UsersController(mockData.Object);
// Invoke
User user1 = usersController.GetUser("1");
// Assert
Assert.NotNull(user1);
Assert.AreEqual(1, user1.ID);
Assert.AreEqual("Anka", user1.LASTNAME);
}

How to Update an Appointment from Exchange Web Service Managed API 2.0 in ASP.NET

iam using the EWS Managed API 2.0 to create an Appontment. It works fine. But want to Update an existing Appointment, too.
I read that i need the appointment ID to specify which appoint should be edited. But where is the ID?
Here is how i create an Appointment:
'Creates the Appointment
Dim appointment As New EWS.Appointment(esb)
appointment.Subject = txtThema.Text
appointment.Body = txtBemerkung.Text
appointment.Start = Von
appointment.End = Bis
appointment.Location = lbRaumInfo.Text
'Adds the Attendees
For i = 1 To emaillist.Length - 1
appointment.RequiredAttendees.Add(emaillist(i))
Next
'Sending
appointment.Save(EWS.SendInvitationsMode.SendToAllAndSaveCopy)
The temporary unique ID for the AppointmentItem can be retrieved via the ItemSchema's Id property. It should be present after saving the AppointmentItem.
ItemId id = appointment.Id;
The ItemId can change if the AppointmentItem is moved or copied.
A way to do it, is to use the Unique ID as suggested by SilverNinja, and as he said that this is not permanent ID and it can be changed once the appointment is moved to different folder (like if it has been deleted for example).
A way to deal with this problem is to create an extended property, and put guid for the appointment, and it wont change unless you made a copy from another appointment (after all it is just a property)
I have it in C# , but I am sure it is pretty easy to convert to VB
private static readonly PropertyDefinitionBase AppointementIdPropertyDefinition = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "AppointmentID", MapiPropertyType.String);
public static PropertySet PropertySet = new PropertySet(BasePropertySet.FirstClassProperties, AppointementIdPropertyDefinition);
//Setting the property for the appointment
public static void SetGuidForAppointement(Appointment appointment)
{
try
{
appointment.SetExtendedProperty((ExtendedPropertyDefinition)AppointementIdPropertyDefinition, Guid.NewGuid().ToString());
appointment.Update(ConflictResolutionMode.AlwaysOverwrite, SendInvitationsOrCancellationsMode.SendToNone);
}
catch (Exception ex)
{
// logging the exception
}
}
//Getting the property for the appointment
public static string GetGuidForAppointement(Appointment appointment)
{
var result = "";
try
{
appointment.Load(PropertySet);
foreach (var extendedProperty in appointment.ExtendedProperties)
{
if (extendedProperty.PropertyDefinition.Name == "AppointmentID")
{
result = extendedProperty.Value.ToString();
}
}
}
catch (Exception ex)
{
// logging the exception
}
return result;
}

ASP.NET MVC EF Calling MySQL Stored Procedure with Out Parameters

I am using Entity Framework ExecuteStoreQuery to call a MySql stored procedure with output parameter. The store procedure also returns a result set.
I get the following error.
OUT or INOUT argument 2 for routine mydb.mysp is not a variable or NEW pseudo-variable in BEFORE trigger
What is wrong? Is there a better way to call MySql sp with mix of out params and resultset?
Here is the code
var outParam = new MySqlParameter();
outParam.ParameterName = "totalRowsOut";
outParam.MySqlDbType = MySqlDbType.Int64;
outParam.Direction = ParameterDirection.Output;
var data = db.ExecuteStoreQuery<PropertySearchResultRow>
(
"call mysp(#input1, #totalRowsOut);",
new MySqlParameter("input1", 10),
outParam
);
var result = data.ToList();
int totalRowsCount = (int)outParam.Value;
Finally ended up using the ado.net MySqlCommand to call the stored proc and get the out value. Mysql and EF integration is bad.
You just need to specify the name of the stored procedure and pass in the parameters. Something like this
var data = db.ExecuteStoreQuery<PropertySearchResultRow>
(
"mysp",new MySqlParameter("input1", 10),outParam
);
Here is my sample code working with VS2012 and Mysql connector 6.8.3 hope this helps someone
public static IList<MyClass> GetCustOrderHist(string someParameter)
{
IList<MyClass> data = ((IObjectContextAdapter)TestDashboardEntities).ObjectContext.ExecuteStoreQuery<MyClass>("CALL CustOrderHist({0});", someParameter).ToList();
return data;
}
public class MyClass
{
public string ProductName { get; set; }
public int TOTAL { get; set; }
}

Resources