0

I have some problems with using database in my Model. I suspect that its not good idea to use database queries in Model, but I don't know how to do it better.

Code:

Let's assume that I have some application to analize football scores. I have some EF model that stores info about footballer:

public class Player
{
[...]
public virtual ICollection<Goal> HisGoals { get; set; }
public float Efficiency
    {
        get
        {
            using(var db = new ScoresContext())
            {
                var allGoalsInSeason = db.Goals.Count();
                return HisGoals.Count / allGoalsInSeason;
            }
        }
    }
}

Problem:

So the case is: I want to have a variable in my model called "Efficiency" that will return quotient of two variables. One of them contains data got in real-time from database. For now this code doesn't work. "Efficiency" equals 0. I tried to use debugger and all data is correct and it should return other value.

What's wrong? Why it returns always zero?

My suspicions:

Maybe I'm wrong, I'm not good at C#, but I think the reason that Efficiency is always zero, is because I use database in it and it is somehow asynchronous. When I call this variable, it returns zero first and then calls the database.

3
  • put a break point on your return statement line and then let us know the value of db.Goals.Count(), also is there any value in HisGoals? Commented Nov 1, 2015 at 20:07
  • @SimonPrice As I said in my question, I tried to check variables in debugger. HisGoals.Count equals 4, allGoals - 11. Commented Nov 1, 2015 at 20:09
  • I dont see where you say where you get your values. rather than put the sum in the return statements put it into a variable and like var result = HisGoals.Count / allGoalsInSeason; do you get a valid result out of this? Commented Nov 1, 2015 at 20:18

1 Answer 1

1

I think that your problem lies in dividing integer / integer. In order to get a float you have to cast first one to float like this:

public float Efficiency
{
   get
   {
       using(var db = new ScoresContext())
       {
           var allGoalsInSeason = db.Goals.Count();
           return (float)HisGoals.Count / allGoalsInSeason;
        }
    }
}

Dividing int/int results always in int that is in your case 0 (if it is as you said in comment 4/11).

Second thing is that Entity Framework will cache values - test it before shipping to production.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, now it works :) But can you explain your last sentence about caching values? What do you mean?
And do you think that using database this way in Model is a good idea? Am I doing it right? How would you do it?
I haven't been working with EF extensively for some time but I remember that if you change value directly in database between calls EF may not hit database twice. Instead it caches value and next time may return old value. This may be a problem if you have other processes running and changing data. Not sure if I am right.
I probably wouldn't hit db this way. First: it is hard to test - it creates tight coupling between your class and DbContext, second: eventually you will forget which method his db which not and it may cause serious problems in runtime - ef is not much forgiving. I would prefer to create DTO object like PlayerStatistics that are snapshot of the system state. Then a repository (see repository pattern) to handle retrieval of this DTO.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.