Qual è il modo migliore per ottenere dati dal database per i dati che vengono utilizzati di frequente?

3

Dice, ho una tabella dei dipendenti, con {id, nome, unità, ecc.} qual è il modo migliore per ottenere questi dati se uso frequentemente questi dati, la mia prima opzione è di interrogarli dal database quando necessario, qualcosa di simile,

public static List<Employee> GetEmployees(string unitID)
{
    List<Employee> employees = new List<Employee>();

    using (SqlConnection sqlConn = new SqlConnection(string.Format(constring, UserID, Password, Server, Database)))
    {
        using (SqlCommand sqlComm = new SqlCommand(string.Format("SELECT ID, Name FROM Employee WHERE UnitID = {0} ORDER BY Name", unitID), sqlConn))
        {
            try
            {
                sqlConn.Open();
                using (SqlDataReader sqlReader = sqlComm.ExecuteReader())
                {
                    if (sqlReader.HasRows)
                    {
                        while (sqlReader.Read())
                        {
                            Employee employee = new Employee()
                            {
                                ID= sqlReader["ID"].ToString(),
                                Name = StaticField.id_ID.TextInfo.ToTitleCase(sqlReader["Name"].ToString())
                            };
                            employees.Add(employee);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBoxEx.Show(ex.Message, "GetEmployees Error", MessageBoxButton.OK, MessageBoxImage.Stop);
            }

            return employees;
        }
    }
}

Oppure seconda opzione, crea DataSet, quindi aggiungi la tabella dei dipendenti come TableAdapter sul set di dati.

var employeeListTableAdapter = new DataSetEmployeeTableAdapters.EmployeeListTableAdapter();
employeeListTableAdapter.ClearBeforeFill = true;
employeeListTableAdapter.Fill(dataset.EmployeeList);

quindi quando ho bisogno di filtrare la riga, uso solo qualcosa di simile.

DataView data = dataset.EmployeeList.DefaultView;
data.RowFilter = string.Format("Unit = {0}", unitID);
    
posta SIRS 31.01.2017 - 08:08
fonte

2 risposte

1

Per renderlo davvero flessibile e trasparente, hai bisogno di un'interfaccia e di un paio di classi concrete che implementano l'interfaccia, e di evitare classi e metodi statici per una vera programmazione orientata agli oggetti:

public interface IEmployeeRepository
{
    IEnumerable<Employee> FindByUnit(int unitId);
    Employee Find(int id);
}

Sto aggiungendo un metodo Find all'interfaccia per illustrare in seguito la difficoltà di memorizzare nella cache questi oggetti.

Ora, la classe EmployeeRepository implementa l'interfaccia IEmployeeRepository , che interroga il database ogni volta:

public class EmployeeRepository : IEmployeeRepository
{
    public EmployeeRepository(string connectionString)
    {
        if (string.IsNullOrEmpty(connectionString))
            throw new ArgumentNullException("connectionString");

        this.connectionString = connectionString;
    }

    private string connectionString;

    public Employee Find(int id)
    {
        // Query by Id and return a single Employee
    }

    public IEnumerable<Employee> FindByUnit(int unitId)
    {
        // Query the database and return the list of employees
    }
}

Ora un codice che utilizza la classe e l'interfaccia concrete:

IEmployeeRepository repository = new EmployeeRepository("...");

IEnumerable<Employee> employees = repository.FindByUnit("3");

Questo ti porta dove sei attualmente. Il database viene interrogato ogni volta. Ora possiamo introdurre alcuni caching:

public class CachedEmployeeRepository : IEmployeeRepository
{
    public CachedEmployeeRepository(IEmployeeRepository employees)
    {
        if (employees == null)
            throw new ArgumentNullException("employees");

        this.employees = employees;
        this.cacheById = new Dictionary<int, Employee>();
        this.cacheByUnitId = new Dictionary<int, Employee>();
    }

    private Dictionary<int, Employee> cacheById;

    private Dictionary<int, IEnumerable<Employee>> cacheByUnitId;

    public Employee Find(int id)
    {
        Employee employee = null;

        if (cacheById.ContainsKey(id))
        {
            employee = employees.Find(id);

            if (employee != null)
            {
                cacheById[id] = employee;
            }
        }
        else
        {
            employee = cacheById[id];
        }

        return employee;
    }

    public IEnumerable<Employee> FindByUnit(int unitId)
    {
        if (cacheByUnitId.ContainsKey(unitId))
        {
            return cacheByUnitId[unitId];
        }

        IEnumerable<Employee> results = employees.FindByUnit(unitId);

        if (results.Any())
        {
            cacheByUnitId[unitId] = results;
        }

        return results;
    }
}

Il CachedEmployeeRepository prende un EmployeeRepository nel suo costruttore e implementa l'interfaccia IEmployeeRepository . Ora puoi introdurre la cache senza problemi nella tua applicazione:

IEmployeeRepository repository = new CachedEmployeeRepository(
    new EmployeeRepository("..."));

IEnumerable<Employee> employees = repository.FindByUnit("3");

Il resto del codice non sa nemmeno, o ha bisogno di sapere, che il caching sta accadendo.

Ma attenzione con il caching. Osserva la ricerca di un dipendente da parte di Id e un elenco di essi per ID unità ha cache diverse e quindi diverse istanze della classe Employee .

There are two hard things in computer science: cache invalidation, naming things, and off-by-one errors. - Martin Fowler

    
risposta data 31.01.2017 - 16:01
fonte
1

È possibile implementare una cache semplice come questa:

public class DatabaseHelper
{
    static private Dictionary<string,List<Employee>> _lookup = new Dictionary<string, List<Employee>>();

    static public List<Employee> GetEmployees(string unitID, bool refresh)
    {
        List<Employee> list;

        if (!refresh)
        {            
            bool exists = _lookup.TryGetValue(unitID, out list);
            if (exists) return list;
        }

        list = GetEmployees(unitID);
        _lookup[unitID] = list;
        return list;
    }

   static private List<Employee> GetEmployees(string unitID)
   {
       //You already wrote this part
   }
}
    
risposta data 31.01.2017 - 10:03
fonte

Leggi altre domande sui tag