Каква е разликата между Single и FirstOrDefault?

Възможен дубликат:
LINQ Single срещу First

Нов съм в Linq и искам да го науча по най-добрия начин, имам тук 2 работещи събития за актуализиране на linq, те правят същото, но кой начин е най-добрият и трябва ли да добавя нещо, за да го направя по-добър!?

Решение 1

Protected Sub Button2_Click(sender As Object, e As System.EventArgs) Handles Button2.Click
    Using db As New ThedatabaseconnectionDataContext()
        Try
            Dim TheUpdateID = DirectCast(FindControl("Textbox5"), TextBox).Text
            Dim getEditing As testtable = (From c In db.testtables Where c.test_id = TheUpdateID Select c).FirstOrDefault()
            If getEditing IsNot Nothing Then
                getEditing.test_cat = DirectCast(FindControl("Textbox1"), TextBox).Text
                getEditing.test_info = DirectCast(FindControl("Textbox2"), TextBox).Text
                getEditing.test_number = DirectCast(FindControl("Textbox3"), TextBox).Text
                getEditing.test_datetime = DirectCast(FindControl("Textbox4"), TextBox).Text
                db.SubmitChanges()
                'textBox1.Text = "Contact updated."
            End If
        Catch ex As Exception
            'Me.lblMsg.Text = ex.Message
        End Try
    End Using
End Sub

Решение 2

Protected Sub Button2_Click(sender As Object, e As System.EventArgs) Handles Button2.Click
    Using db As New ThedatabaseconnectionDataContext()
        Try
            Dim tbltest As Table(Of testtable) = db.GetTable(Of testtable)()
            Dim TheUpdateID = DirectCast(FindControl("Textbox5"), TextBox).Text
            Dim getEditing As testtable = tbltest.Single(Function(c) c.test_id = TheUpdateID)
            If getEditing IsNot Nothing Then
                getEditing.test_cat = DirectCast(FindControl("Textbox1"), TextBox).Text
                getEditing.test_info = DirectCast(FindControl("Textbox2"), TextBox).Text
                getEditing.test_number = DirectCast(FindControl("Textbox3"), TextBox).Text
                getEditing.test_datetime = DirectCast(FindControl("Textbox4"), TextBox).Text
                db.SubmitChanges()
                'textBox1.Text = "Contact updated."
            End If
        Catch ex As Exception
            'Me.lblMsg.Text = ex.Message
        End Try
    End Using
End Sub

person Thomas Bøg Petersen    schedule 24.09.2012    source източник
comment
@KirkBroadhurst всъщност не е дубликат imo (така или иначе на свързания въпрос) това пита кой да се използва в кои сценарии, този, който сте свързали, пита кой е по-ефективен за един запис   -  person Manatherin    schedule 24.09.2012


Отговори (2)


Откъде дори да започна с това...

За начало знам, че това вероятно е тестов проект, така че се извинявам, ако вече го правите, но моля, уверете се, че използвате приемливи йерархии на нива на данни - вашият DBML трябва да бъде в отделен проект от вашия презентационен слой.

Но към въпроса в ръка. Предпочитаният от мен начин да направя това е да получа обекта с данни и да го актуализирам на ниво обект. Като например (псевдо код / ​​аз съм C# някак човек!):

private MyObject object;

protected void Page_Load(object sender, EventArgs e)
{
    // Select usually be ID
    object = DataLayer.GetObject();

    if(!IsPostBack)
    {
         // Load object details for editing into presentation layer
         TextboxObjectName.Text = object.Name;
    }
}

protected void Button_Click(object sender, EventArgs e)
{
     // Button click event - update object and send it to database
     object.Name = TextboxObjectName.Text;

     DataLayer.UpdateObject(object);
}

Това използва проследяване на обекти и тогава слоят Daya може да изглежда така:

function void UpdateObject(MyObject obj)
{
    using (TestDataContext db = new TestDataContext ())
    {

       db.MyObjects.Attach(obj);

       db.Refresh(RefreshMode.KeepCurrentValues, obj);

       db.SubmitChanges();
    }
}
person Chris Dixon    schedule 24.09.2012
comment
MyObject на същата страница ли е или във файл на клас!? Къде посочвате какъв ID да актуализирате!? - person Thomas Bøg Petersen; 24.09.2012
comment
MyObject е автоматично генерираният клас, който вашият DBML ще генерира. Да кажем, че ако вашата таблица е наречена Files, тогава ще имате автоматично генериран клас, наречен File, в който ще се проследява от Entity Framework. ID за избор на обекта може да се види в коментара Page_Load. - person Chris Dixon; 24.09.2012

Първо, трябва да можете да напишете своя първи или по подразбиране като

Dim getEditing As testtable = tbltest.FirstOrDefault(Function(c) c.test_id = TheUpdateID)

Не е тестван, но трябва да отбележа, че first или default обработва ламбда

Що се отнася до това кой да използвате, зависи от вашите данни. Да разбиеш какво се случва

Единичен - Очаква се точно едно съвпадение, хвърля се изключение, ако не бъдат намерени резултати ИЛИ са намерени множество резултати

SingleOrDefault - Очаква 0 или 1 съвпадение. Изключение се хвърля, ако бъдат намерени множество съвпадения

Първо - Очаква 1 или много съвпадения. Изключение се хвърля, ако не бъдат намерени съвпадения. Всички резултати след първия резултат се игнорират.

FirstOrDefault - обработва 0, 1 или множество съвпадения. Всички резултати след първия резултат се игнорират.

Ако избирате въз основа на идентификатор от списъчно поле (т.е. той е уникален и определено е в базата данни), тогава единичният е безопасен избор.

Ако потребителят въвежда ID (отново уникален), който може или не може да бъде в DB, ​​единичният или по подразбиране е безопасен.

Ако търсите въз основа на възможна дублирана стойност, като фамилно име, първо или първо по подразбиране е това, което трябва да използвате в зависимост дали е гарантирано, че съществува в базата данни или не.

Лично аз, независимо от данните, бих се придържал към first или firstordefault, тъй като обработва повече сценарии.

person Manatherin    schedule 24.09.2012
comment
Може би допълнение: „FirstOrDefault – обработва 0, 1 или множество съвпадения“ – но игнорира всичко след първото съвпадение - person Hans Kesting; 24.09.2012
comment
@HansKesting Добра точка, промених отговора си - person Manatherin; 24.09.2012
comment
Страхотен отговор......Просто добавяне, ако имам това, което препоръчвате........Dim tbltest As Table(Of testtable) = db.GetTable(Of testtable)() Dim TheUpdateID = DirectCast( FindControl(Textbox5), TextBox).Text Dim getEditing As testtable = tbltest.FirstOrDefault(Function(c) c.test_id = TheUpdateID) Как да използвам INNER, ако моята таблица е с имена testtable и maintable и искам да получа информацията от maintable , където main_id = test_id !? - person Thomas Bøg Petersen; 24.09.2012
comment
@ThomasBøgPetersen Не съм сигурен, че разбирам какво имаш предвид - person Manatherin; 24.09.2012
comment
Хей Manatherin, имам предвид как да направя (в този случай) Dim tdltest, ако имам тази стара sql заявка, която получава информация от 2 таблици..... Dim cmd като нова SqlCommand(SELECT Groups.Name FROM Roles INNER JOIN Groups ON Roles.GroupID = Groups.GroupID INNER JOIN Users ON Roles.UserID = Users.UserID И Users.Username=@UserName, conn) - person Thomas Bøg Petersen; 24.09.2012
comment
@ThomasBøgPetersen като цяло бих казал, че трябва да направите запитване до потребителя и да преминете през релациите, например да получите потребителя, да извикате .Groups, след което можете да изберете много, за да получите имената на групите като .Groups.SelectMany(x =› x.Roles.select(y =› y.Name)), Нищо от това не е тествано и вероятно няма да се компилира, но само за да ви дам представа. Като алтернатива можете да извикате съхранена процедура или да изпълните SQL от рамка на обект. Можете да се присъедините към LINQ, но аз се опитвам да не използвам тази функция, така че някой друг може да е в състояние да ви помогне повече, ако го зададете като отделен въпрос. - person Manatherin; 25.09.2012